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

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Farbraum&amp;diff=19527</id>
		<title>Farbraum</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Farbraum&amp;diff=19527"/>
				<updated>2006-08-31T15:21:44Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Übersicht ==&lt;br /&gt;
Farbräume dienen der Darstellung von Farben. Üblicherweise werden alle an Monitoren darstellbaren Farben durch 3 Grundtöne codiert. Durch verschieden starke Abstufungen dieser 3 Grundtöne entsteht der Eindruck von verschiedenen Farben. &lt;br /&gt;
&lt;br /&gt;
== Grundlegende Bildschirmkalibrierung ==&lt;br /&gt;
Um die dargestellten Farben an Computermonitoren optimal anzuzeigen, muss der Monitor zuerst kalibriert werden. Für unsere Zwecke soll eine einfache Kalibrierung ausreichen: In professionellem Umfeld kommt es nicht nur auf optimale Farbdarstellung an, sondern auch auf Farbechtheit. Um dies zu erreichen ist nicht ganz billiges Equipment notwendig. Wir wollen uns deshalb auf ein paar Hausmittel beschränken. Tatsächlich sind die meisten Computermonitore derart schlecht eingestellt, daß man bei weitem nicht von guter Farbdarstellung reden kann. Bevor wir also weitermachen, wollen wir diesen Umstand ändern. Zuerst muss der Monitor jedoch warm sein - also mindestens eine Stunde in Betrieb sein, bevor er eingestellt wird. &lt;br /&gt;
&lt;br /&gt;
=== Schwarzpunkt ===&lt;br /&gt;
Macht euer Zimmel dunkel. Alle Beleuchtung muss abgestellt werden. Eventuelle Rolläden werden bitte geschlossen. Stellen wir die Helligkeit des Monitors auf das Minimum und betrachten das untere Bild (wenn du nach dem dunkelstellen nichts mehr sehen kannst solltest du den folgenden Teil der Anleitung vorher durchlesen):&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Schwarzpunkt.png|center]]&lt;br /&gt;
&lt;br /&gt;
Stelle nun die Helligkeit soweit nach oben, bis das schwarze Bild gerade beginnt heller zu erscheinen. Ist dieser Punkt erreicht, dann stelle die Helligkeit wieder ein kleines Stück zurück, so daß es wieder komplett schwarz ist. Wenn das Bild partout nicht hell werden möchte, dann stelle die Helligkeit auf ein Maß, so daß der Mointor nicht zu hell leuchtet ( ein zu heller Monitor ist sehr unangenehm für die Augen. Wenn ihr beim längeren arbeiten Augenschmerzen oder Tränen in den Augen bekommt, dann stellt die Helligkeit unbedingt weiter zurück. Soviel ist der optimale Schwarzpunkt nicht wert. ). '''Achtung TFT Benutzer:''' Der Helligkeitsverlauf auf TFT Monitoren ist nicht konstant. Ich empfehle deshalb das Bild etwa mittig zu plazieren.&lt;br /&gt;
&lt;br /&gt;
=== Kontrast und Gamma === &lt;br /&gt;
[[Bild:Farbräume_Kontrast.png|center]]&lt;br /&gt;
&lt;br /&gt;
Betrachtet bei den obigen Farbverläufen den von Schwarz nach Weiß. Alle 24 Felder sind gleich groß. Der erste Übergang von Schwarz nach etwas Helligkeit sollte in etwa so stark ausfallen, wie der von Weiß auf die erste Abstufung. Regelt die Kontrasteinstellung eures Monitores solange bis beide Übergänge tatsächlich sichtbar sind und in etwa gleich stark ausfallen. Die anderen Felder sollten sich dann bereits halbwegs angepasst haben: Der Verlauf erscheint linear. Wenns noch nicht ganz passt, könnt ihr am Monitor ( wenn das der Monitor nicht bietet, benutzt die Einstellungsmöglichkeiten eures Grafikkartentreibers ) den Gammawert noch ein wenig korrigieren. &lt;br /&gt;
&lt;br /&gt;
Falls ihr gerne noch etwas mehr Zeit investieren wollt, danns schaut doch mal [http://tom.via.de/Fotoseiten/Kalibrierung/kalibrierung.asp hier] oder [http://de.wikipedia.org/wiki/Gammakorrektur#Gamma-Testgrafik hier] vorbei. Auf diesen und auf vielen anderen Seiten im Netz wird beschrieben, wie man seinen Monitor einstellen kann - meine Anleitung gehört doch eher zu den primitiven. Falls das Bild des Monitors jetzt eher grau und milchig erscheint, seid ihr wahrscheinlich dem Problem erlegen, daß unsere Augen logarithmische Farbveränderungen bevorzugen und lineare Verläufe eher ungewohnt sind - dann ist es Zeit, sich eine etwas genauere Beschreibung zum Thema Bildschirm-justierung/kalibrierung durchzulesen.&lt;br /&gt;
&lt;br /&gt;
== Physikalische und biologische Grundlagen ==&lt;br /&gt;
Physikalisch besteht Licht aus Wellen. Diese haben verschiedene Wellenlaengen und je nach Zusammensetzung entsteht der eine oder der andere Farbeindruck.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Farbspektrum.png|center]] &lt;br /&gt;
&lt;br /&gt;
Das sichtbare Licht hat Wellenlängen zwichen 400nm (Violett) bis 750 nm (Rot). Bei kürzeren Wellenlängen unter 400nm kommen dann Ultra Violette, Röntgen und schließlich Gamma Strahlen. Auf der anderen Seite über 750 nm folgen Infrarot, Mikrowellen, Funkempfang (LW, MW, UKW, ...), usw. Auf dem Monitor lassen sich nicht alle Reinfarben darstellen, seht das obige Bild also eher als Eindruck statt als &amp;quot;so siehts also aus&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Da unser Auge nur 3 Grundfarben unterscheiden kann (manche Menschen können sogar 4 Farben unterscheiden, wieder andere dagegen nur 2.), kann man verschiedene Farbeindrücke nicht nur durch verschiedene Wellenlängen erzeugen,  sondern auch durch das Mischen und Verlagern der Intensitäten einer Reihe von Grundfarben. So wird am Monitor  bekanntlich (additiv) mit Rot, Grün und Blau, auf Printmedien üblicherweise (subtraktiv) mit Cyan, Gelb, Magenta und Schwarz gemischt. Man kann so zwar nicht jede sichtbare Farbe mischen, aber doch so viele, daß ein guter Farbeindruck entsteht.&lt;br /&gt;
&lt;br /&gt;
== Verschiedene Farbräume ==&lt;br /&gt;
=== RGB ===&lt;br /&gt;
Der Rot, Grün, Blau Farbraum ist der Standardfarbraum für Computer und viele andere Bildschirmgeräte. Damit Farben aus anderen Farbräumen auf einem solchen Gerät dargestellt werden können, müssen sie immer zuerst auf diesen Farbraum umgerechnet werden. Er ist neben CMY einer der am wenigsten anschaulichen Farbräume. Farben lassen sich darin nur sehr schlecht identifizieren, sinnvolle Farbmanipulationen sind kaum möglich. Der Vorteil ist jedoch, daß die 3 Grundfarben etwa denen entsprechen, die auch auf unserer Netzhaut am besten erkannt werden - die Folge: höchst brilliante Farben, die einen großen Teil aller sichtbaren Farben abdecken. Den Farbraum kann man sich als dreidimensionalen Würfel am Nullpunkt vorstellen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_RGB.png|center]] &lt;br /&gt;
&lt;br /&gt;
Ausgehend vom Schwarz kann man nach rechts (Rot), nach oben (Grün) oder nach vorne (Blau) laufen und erhält immer hellere Farben. Schließlich gelangt man zum Weiß. Dazu gibt es auch eine weitere Veranschaulichung:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_RGB_additiv.png|center]] &lt;br /&gt;
&lt;br /&gt;
=== CMY ===&lt;br /&gt;
Der Cyan, Magenta, Gelb Farbraum ist dem RGB Farbraum sehr ähnlich. Allerdings ist er für Printmedien konzipiert. Ist keine Farbe aufgetragen, so erhält man den Hintergrund - meist ein weißes Blatt Papier. Je mehr man von einer Farbe aufträgt, desto weniger scheinen die anderen Farben durch - trägt man also alle Farben auf, bleibt vom ursprünglichen Weiß nichts über und man erhält Schwarz. Da jedoch der Hintergrund im Allgemeinen nicht leuchtet, können Farben nie derart hell erscheinen, wie im RGB Farbraum - man möge dies bei Druck-Anwendungen beachten:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_CYM.png|center]] &lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_CYM_subtraktiv.png|center]]&lt;br /&gt;
&lt;br /&gt;
Zum Umrechnen von RGB in CMY ist nicht viel nötig:&lt;br /&gt;
 R = 1-C&lt;br /&gt;
 G = 1-M&lt;br /&gt;
 B = 1-Y&lt;br /&gt;
Und umgekehrt:&lt;br /&gt;
 C = 1 - R&lt;br /&gt;
 M = 1 - G&lt;br /&gt;
 Y = 1 - B&lt;br /&gt;
&lt;br /&gt;
=== CMYK ===&lt;br /&gt;
Der CMYK Farbraum entspricht im wesentlichen dem CMY Farbraum, mit dem Unterschied, daß zusätzlich Schwarz zum Beimischen zur Verfügung steht. Dies kann beim Drucken von sehr dunklen Tönen hilfreich sein und spart ausserdem die teure Farbe. In manchen Fällen ist es sogar unumgänglich mit Schwarz zu drucken, wenn sich durch die anderen Druckfarben kein richtiges Schwarz erzeugen lässt (was häufig der Fall ist, u.a. auch bei den meisten Tintendruckern). &lt;br /&gt;
&lt;br /&gt;
Umrechnen CMYK nach CMY:&lt;br /&gt;
 CMY.C = C * ( 1 - K ) + K&lt;br /&gt;
 CMY.M = M * ( 1 - K ) + K&lt;br /&gt;
 CMY.Y = Y * ( 1 - K ) + K&lt;br /&gt;
&lt;br /&gt;
Umrechnen CMY nach CMYK&lt;br /&gt;
 CMYK.K = min(C,M,Y);&lt;br /&gt;
 if ( CMYK.K == 1 ) { &lt;br /&gt;
   CMYK.C = 0;   &lt;br /&gt;
   CMYK.M = 0;&lt;br /&gt;
   CMYK.Y = 0;&lt;br /&gt;
 } else {&lt;br /&gt;
   CMYK.C = (C-CMYK.K)/(1-CMYK.K);   &lt;br /&gt;
   CMYK.M = (M-CMYK.K)/(1-CMYK.K);   &lt;br /&gt;
   CMYK.Y = (Y-CMYK.K)/(1-CMYK.K);   &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== HSV ===&lt;br /&gt;
Der Hue, Saturation, Value (Farbton, Sättigung, Helligkeit) ist ein Farbraum, der sehr häufig im Einsatz ist. Da der Farbton als solches an einem Kanal zu identifizieren ist, werden viele Bildoperationen, die mit Farbe zu tun haben, in eben diesem Farbraum berechnet. Eine bildliche Vorstellung dieses Farbraums ist sehr viel einfacher, als die des RGB Farbraums. Wie also kann man sich ihn vorzustellen?&lt;br /&gt;
&lt;br /&gt;
Eine gute Möglichket ist als Zylinder. Die Unterseite ist schwarz. Bewegt man sich von der Mitte der Unterseite auf die gegenüberliegende Seite zu, wird es heller. Inmitten der hellen Seite ist Weiß. Geht man von dort nach aussen, erhöht sich die Farbsättigung. Geht man dann auf dem Kreis spazieren, bleibt Helligkeit und Sättigung konstant, während sich die Farbe ändert. Dieses Prinzip wird bei vielen Farbauswahldialogen angewendet (Im Beispiel: Paint.NET) :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_HSV_auswahl1.png|center]] &lt;br /&gt;
&lt;br /&gt;
Der Kreis stellt die farbige Oberseite des Zylinders dar. Von der Mitte nach Aussen also die Sättigung, den Umfang entlang die Farbe. Der Balken beschreibt die Helligkeit. Sehr beliebt ist auch die aufgefaltete Variante (MS-Windows Standard Farbauswahl Dialog):&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_HSV_auswahl2.png|center]]&lt;br /&gt;
&lt;br /&gt;
Im quadratischen Feld ist von Links nach Rechts die Farbe, von Unten nach Oben die Sättigung aufgetragen. Der Balken gibt wieder die Helligkeit an. &lt;br /&gt;
&lt;br /&gt;
Es existieren noch viele verschiedene Varianten, die alle mehr oder weniger identisch funktionieren. Wir wollen es bei diesen zwei Beispielen belassen.&lt;br /&gt;
&lt;br /&gt;
Die Farbreihenfolge wird gewöhnlich definiert als Rot, Magenta, Blau, Cyan, Grün, Gelb, Rot. Zwischen den Vollfarben wird linear interpoliert, was zu folgenden Umrechnungen führt:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
        // Based on C Code in &amp;quot;Computer Graphics -- Principles and Practice,&amp;quot;&lt;br /&gt;
        // Foley et al, 1996, p. 593.&lt;br /&gt;
        public static RGB HSVToRGB(double h, double s, double v)&lt;br /&gt;
        {&lt;br /&gt;
            double f, hTemp, p,q,t;&lt;br /&gt;
            int i;&lt;br /&gt;
            RGB Result = new RGB();&lt;br /&gt;
            if (s == 0) {&lt;br /&gt;
                //Achromatic&lt;br /&gt;
                Result.R = v;&lt;br /&gt;
                Result.G = v;&lt;br /&gt;
                Result.B = v;&lt;br /&gt;
                return Result;&lt;br /&gt;
            }&lt;br /&gt;
            if (h &amp;lt; 0)&lt;br /&gt;
                h = Math.PI * 2 - h;&lt;br /&gt;
       &lt;br /&gt;
            if (h &amp;gt; 2 * Math.PI)&lt;br /&gt;
                h = h - Math.Truncate(1.0 / (Math.PI * 2) *h)* (Math.PI * 2);&lt;br /&gt;
         &lt;br /&gt;
            hTemp = h / (2*Math.PI / 6);&lt;br /&gt;
            i = (int) Math.Truncate(hTemp);  // largest integer &amp;lt;= h&lt;br /&gt;
            f = hTemp - i;                   // fractional part of h&lt;br /&gt;
     &lt;br /&gt;
            p = v * (1.0 - s);&lt;br /&gt;
            q = v * (1.0 - (s * f));&lt;br /&gt;
            t = v * (1.0 - (s * (1.0 - f)));&lt;br /&gt;
              &lt;br /&gt;
            switch (i) {&lt;br /&gt;
                case 0: { Result.R = v; Result.G = t; Result.B = p; break; }&lt;br /&gt;
                case 1: { Result.R = q; Result.G = v; Result.B = p; break; }&lt;br /&gt;
                case 2: { Result.R = p; Result.G = v; Result.B = t; break; }&lt;br /&gt;
                case 3: { Result.R = p; Result.G = q; Result.B = v; break; }&lt;br /&gt;
                case 4: { Result.R = t; Result.G = p; Result.B = v; break; }&lt;br /&gt;
                case 5: { Result.R = v; Result.G = p; Result.B = q; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return Result;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        // Based on C Code in &amp;quot;Computer Graphics -- Principles and Practice,&amp;quot;&lt;br /&gt;
        // Foley et al, 1996, p. 594.&lt;br /&gt;
        public static HSV RGBToHSV(double r, double g, double b)&lt;br /&gt;
        {&lt;br /&gt;
            HSV result = new HSV();&lt;br /&gt;
            double delta, min;&lt;br /&gt;
    &lt;br /&gt;
            min = Math.Min(r, Math.Min(g, b));&lt;br /&gt;
            result.v = Math.Max(r, Math.Max(g, b));&lt;br /&gt;
            delta = result.v - min;&lt;br /&gt;
        &lt;br /&gt;
            // Calculate saturation: saturation is 0 if r, g and b are all 0&lt;br /&gt;
            if (result.v == 0.0)&lt;br /&gt;
                result.s = 0;&lt;br /&gt;
            else&lt;br /&gt;
                result.s = delta / result.v;&lt;br /&gt;
   &lt;br /&gt;
            if (result.s == 0)&lt;br /&gt;
                result.h = 0; //Achromatic&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                if (r == result.v)&lt;br /&gt;
                {   //winkel zw. gelb/magenta&lt;br /&gt;
                    result.h = (g - b) / delta * (2 * Math.PI / 6.0);&lt;br /&gt;
                }&lt;br /&gt;
                else if (g == result.v)&lt;br /&gt;
                {    //zwischen cyan und gelb&lt;br /&gt;
                    result.h = (2 + (b - r) / delta) * (2 * Math.PI / 6.0);&lt;br /&gt;
                }&lt;br /&gt;
                else if (b == result.v)&lt;br /&gt;
                {// ...&lt;br /&gt;
                    result.h = (4 + (r - g) / delta) * (2 * Math.PI / 6.0);&lt;br /&gt;
                }&lt;br /&gt;
                if (result.h &amp;lt; 0)&lt;br /&gt;
                    result.h = result.h + 2 * Math.PI;&lt;br /&gt;
            }&lt;br /&gt;
            return result;&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== HSL ===&lt;br /&gt;
Der Hue Saturation Lightness Farbraum ist dem HSV Farbraum sehr ähnlich. Die Definition des Farbtons (Hue) ist identisch, lässt sich also auf die gleiche Weise berechnen. Die anderen Werte berechnen sich aus den RGB Werten wie folgt:&lt;br /&gt;
 MAX = max (R,G,B);&lt;br /&gt;
 MIN = min (R,G,B);&lt;br /&gt;
 &lt;br /&gt;
 L = (1.0/2.0) * (MAX + MIN);&lt;br /&gt;
 if (MIN == MAX) &lt;br /&gt;
 {&lt;br /&gt;
   S = 0&lt;br /&gt;
 } else if (L &amp;lt;= 1.0/2.0) {&lt;br /&gt;
   S = (MAX - MIN) / (2.0*L) &lt;br /&gt;
 } else {&lt;br /&gt;
   // entspr. Fall: L &amp;gt; 1.0/2.0&lt;br /&gt;
   S = (MAX - MIN) / (2.0-2.0*L)  &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Man stellt sich den HSV Farbraum gerne als Doppelkonus vor. Die obere Spitze ist weiß, die untere schwarz. Am Rand des Bauches befinden sich die Vollfarben, die zur Mitte hin an Sättigung verlieren (Bild: Wikipedia [EN]):&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Color_Cones.png|center]]&lt;br /&gt;
&lt;br /&gt;
=== LAB ===&lt;br /&gt;
Der LAB Farbraum ist einer an das menschliche Sehen angepasster Farbraum. Er umfasst alle vom Auge unterscheidbaren Farben und ein bischen mehr. Er dient dazu, Farbechtheit zu garantieren, was wichtig ist, wenn man z.B. am Bildschirm Bilder bearbeitet und diese am Ende drucken oder auf Fotopapier auslasern lassen möchte, so daß die Vorlage am Monitor dem entspricht, was auf dem Papier landen wird. Er dient dabei nur als Umrechnungsfarbraum, wobei auf die spezifischen Eigenschaften des jeweilig genutzen Gerätes geachtet werden muss.&lt;br /&gt;
&lt;br /&gt;
== Farbraumspaß ==&lt;br /&gt;
Wir wollen uns hier ein wenig mit den Möglichkeiten des HSV Farbraumes vertraut machen und einige Spielereien ausprobieren. &lt;br /&gt;
=== Vergrauen ===&lt;br /&gt;
Im HSV Farbraum kann man ein Bild sehr einfach in ein Graustufenbild umwandeln, indem man die Sättigung auf 0 stellt:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Rothsee_farbig.png|center]]&lt;br /&gt;
[[Bild:Farbräume_Rothsee_grau.png|center]]&lt;br /&gt;
&lt;br /&gt;
Wenn einem reines S/W zu langweilig ist, kann man auch ein feste Sättigung und Farbe vorgeben, so daß das Bild eingefärbt wird ( S/W-Foto-Material verändert häufig mit dem Alter ein wenig seine Farbe oder ist von vornherein leicht farbig ). Wer Spaß an dieser Art der Bildbearbeitung findet, kann auch noch die Helligkeit anpassen - Schwarzweißfilme sind nach Wellenlängen unterschiedlich empfindlich. Blau wird auf dem positiv häufig heller wiedergegeben als grün, welches wiederum heller als rot erscheint. Viel Spaß beim ausprobieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Rothsee_blackwhitestyle.png|center]]&lt;br /&gt;
&lt;br /&gt;
=== Farbkurven ===&lt;br /&gt;
Wer sich einmal mit einem Bildbearbeitungsprogramm auseinandergesetzt hat, wird sie kennen, die Dialoge zum Verändern der Farbkurven. Die Kurven stellen eine Verschiebungsfunktion dar: Hat man z.B. ein Farbkurve für den roten Farbkanal festgelegt, so beschreibt die Farbkurve f an einer Stelle i den Wert, den ein Punkte im roten Farbkanal hat, wenn er vorher den Wert i hatte, also:&lt;br /&gt;
 Punkt.rot = f(Punkt.rot);&lt;br /&gt;
im Bild: GIMP:&lt;br /&gt;
[[Bild:Farbräume_GIMPColorcurvesdialog.png|center]]&lt;br /&gt;
Diese Idee wollen wir uns zu Eigen machen - so ist es im HSV Farbraum nur zu konsequent, nicht Rot/Grün/Blau, bzw. Cyan/Magenta/Gelb sondern die Hue, Saturation und Value Werte zu manipulieren. Und die Sache ein wenig auf die Spitze zu treiben, wollen wir uns nicht nur mit Hue/Hue und den 2 anderen Kurven beschäftigen, sondern auch mit gemischten, bei denen sich anhand der Farbe die Helligkeit oder Sättigung ändert. Vieles ist hier denkbar.&lt;br /&gt;
&lt;br /&gt;
Um es realisieren zu können, benötigt man zuerst einmal eine eigene Dialogbox, die das Bearbeiten von (Farb-)Kurven zulässt. Im wesentlichen dürfte das niemanden hier überfordern - ich empfehle folgende Szenerie: Die Kurve wird mithilfe von Spline-Interpolation erzeugt. Die Menge der Stützstellen ist im wesentlichen beliebig, für einige Kurven ist es jedoch wichtig, nicht nur natürliche, sondern auch periodische Kurven erzeugen zu können. Genauere Informationen hierzu finden sich in den Literaturangaben.&lt;br /&gt;
&lt;br /&gt;
Die einfachste Art der Kurven ist wie gesagt die, die sich selber beeinflussen. So lassen sich leicht Farben durch andere Farben tauschen, ohne den Rest der Farben zu beeinflussen. Man kann natürlich auch bestimmte Sättigungen hervorheben (also Sättigung/Sättigung statt bei Farben Hue/Hue) oder ähnliches. Als Beispiel wird der Hue-Bereich von Gelb in den von Rot verschoben. Durch feine Abstimmung lässt sich erreichen, daß andere Farben sich dabei nicht verändern (Diesen Effekt kann man noch leicht in Photoshop erreichen, man muss jedoch für jede Farbe getrennt vorgehen, falls man verschiedene Farben verändern möchte: Image/Adjustmennts/Hue-Saturations . Wir können dagegen leicht mehrere Farben auf einmal austauschen.).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Hue_Hue_mapping.png|center]]&lt;br /&gt;
&lt;br /&gt;
Als Alternative noch eine Sättigung/Sättigung Variante des obigen Bildes. Links wurde die 20. Wurzel aus der Sättigung gezogen, rechts wurde die Sättigung zur 4. Potenz erhoben (dies entspricht einer Erniedrigung bzw. Erhöhung des Sättigungkontrastes). Die einstellbaren Kurven lassen sich dazu natürlich genauso benutzen, aber so sparen wir uns ein paar Bilder ;-)&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Sat_Sat_mapping.png|center]]&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir einmal eine Value/Hue Variante betrachten. Ziel ist es, ein Pixel anhand seines Value den Hue weiterzudrehen. Man trägt im Kurvendialog wie folgt an: In Y-Richtung variiert die Hue, in X-Richtung ist Value von 0 bis 1 angetragen. Zu einer bestimmten Value soll also der Hue um einen bestimmten Winkel weitergedreht werden - vorwärts und rückwärtsdrehen sollte möglich sein. Rechnen könnte man dann:&lt;br /&gt;
&lt;br /&gt;
 Pixel.Hue = Pixel.Hue + Kurve(Pixel.Value);&lt;br /&gt;
&lt;br /&gt;
Da Pixel.Hue dadurch auch negative oder zu große Werte annehmen kann, sollte man sie wieder auf den Berech 0 bis 2*Pi zurückrechnen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Val_Hue_mapping.png|center]]&lt;br /&gt;
&lt;br /&gt;
Im obigen Bild ist die zugrundeliegende Kurve die [http://de.wikipedia.org/wiki/Glockenkurve Gaussche Glockenkurve] mit sigma = 0.29, mu = 0.9, d.h. also, daß bei niedrigen value Werten im wesentlichen keine Veränderung des Hue passiert. Je heller die Szene jedoch wird, desto stärker verschiebt sich der Farbton. Da die Lichtquelle im Hintergrund des Fotos ist, verändern sich die Farben stärker, je weiter hinten sich die Luftballons befinden.&lt;br /&gt;
&lt;br /&gt;
Es lassen sich noch einige weitere Varianten vorstellen, als die, die hier gezeigt wurden. So könnte man anhand einer Hue/Sat Kurve bestimmte Farben vergrauen lassen und andere hervorheben - der Effekt ist sicherlich nicht gänzlich unbekannt. In der Fotografie wird gerne entsprechend manipuliert: Man stelle sich ein Mädchen vor, daß eine rote Rose hält. Alle Farben sind grau, nur die Blüte der Rose ist rot - mit Hue/Sat Kurven ist das wirklich sehr leicht zu erreichen.&lt;br /&gt;
&lt;br /&gt;
== Literatur ==&lt;br /&gt;
* [http://www.efg2.com/Lab/Graphics/Colors/index.html Earl F. Glynn II: efg's Palettes and Colors Lab]&lt;br /&gt;
* [http://www.efg2.com/Lab/Library/Color/index.html Earl F. Glynn II: efg's Color Reference Library]&lt;br /&gt;
* [http://www.midnightkite.com/color.html Dan Bruton: Color Science]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Color_model Englische Wikipedia: Color Models. Viele informationen, Veranschaulichungen, Umrechnungsformeln]&lt;br /&gt;
* [http://www.adhocconference.com/cgi-bin/blosxom.cgi/PastShows/MacHack16/2001_papers.html Darrin Cardani: Adventures in HSV Space (als PDF)]&lt;br /&gt;
* [http://de.wikipedia.org/wiki/Spline-Interpolation Wikipedia: Spline interpolation]&lt;br /&gt;
* Bronstein, Semendjajew, Musiol, Mühlig: Taschenbuch der Mathematik. 5 Auflage. S.955: 19.7.1 Kubische Splines&lt;br /&gt;
* [http://www.arndt-bruenner.de/mathe/scripts/kubspline.htm Arndt Brünner: Kubische Splines]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Farbraum&amp;diff=19526</id>
		<title>Farbraum</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Farbraum&amp;diff=19526"/>
				<updated>2006-08-31T15:06:23Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Physikalische und biologische Grundlagen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Übersicht ==&lt;br /&gt;
Farbräume dienen der Darstellung von Farben. Üblicherweise werden alle an Monitoren darstellbaren Farben durch 3 Grundtöne codiert. Durch verschieden starke Abstufungen dieser 3 Grundtöne entsteht der Eindruck von verschiedenen Farben. &lt;br /&gt;
&lt;br /&gt;
== Grundlegende Bildschirmkalibrierung ==&lt;br /&gt;
Um die dargestellten Farben an Computermonitoren optimal anzuzeigen, muss der Monitor zuerst kalibriert werden. Für unsere Zwecke soll eine einfache Kalibrierung ausreichen: In professionellem Umfeld kommt es nicht nur auf optimale Farbdarstellung an, sondern auch auf Farbechtheit. Um dies zu erreichen ist nicht ganz billiges Equipment notwendig. Wir wollen uns deshalb auf ein paar Hausmittel beschränken. Tatsächlich sind die meisten Computermonitore derart schlecht eingestellt, daß man bei weitem nicht von guter Farbdarstellung reden kann. Bevor wir also weitermachen, wollen wir diesen Umstand ändern. Zuerst muss der Monitor jedoch warm sein - also mindestens eine Stunde in Betrieb sein, bevor er eingestellt wird. &lt;br /&gt;
&lt;br /&gt;
=== Schwarzpunkt ===&lt;br /&gt;
Macht euer Zimmel dunkel. Alle Beleuchtung muss abgestellt werden. Eventuelle Rolläden werden bitte geschlossen. Stellen wir die Helligkeit des Monitors auf das Minimum und betrachten das untere Bild (wenn du nach dem dunkelstellen nichts mehr sehen kannst solltest du den folgenden Teil der Anleitung vorher durchlesen):&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Schwarzpunkt.png|center]]&lt;br /&gt;
&lt;br /&gt;
Stelle nun die Helligkeit soweit nach oben, bis das schwarze Bild gerade beginnt heller zu erscheinen. Ist dieser Punkt erreicht, dann stelle die Helligkeit wieder ein kleines Stück zurück, so daß es wieder komplett schwarz ist. Wenn das Bild partout nicht hell werden möchte, dann stelle die Helligkeit auf ein Maß, so daß der Mointor nicht zu hell leuchtet ( ein zu heller Monitor ist sehr unangenehm für die Augen. Wenn ihr beim längeren arbeiten Augenschmerzen oder Tränen in den Augen bekommt, dann stellt die Helligkeit unbedingt weiter zurück. Soviel ist der optimale Schwarzpunkt nicht wert. ). '''Achtung TFT Benutzer:''' Der Helligkeitsverlauf auf TFT Monitoren ist nicht konstant. Ich empfehle deshalb das Bild etwa mittig zu plazieren.&lt;br /&gt;
&lt;br /&gt;
=== Kontrast und Gamma === &lt;br /&gt;
[[Bild:Farbräume_Kontrast.png|center]]&lt;br /&gt;
&lt;br /&gt;
Betrachtet bei den obigen Farbverläufen den von Schwarz nach Weiß. Alle 24 Felder sind gleich groß. Der erste Übergang von Schwarz nach etwas Helligkeit sollte in etwa so stark ausfallen, wie der von Weiß auf die erste Abstufung. Regelt die Kontrasteinstellung eures Monitores solange bis beide Übergänge tatsächlich sichtbar sind und in etwa gleich stark ausfallen. Die anderen Felder sollten sich dann bereits halbwegs angepasst haben: Der Verlauf erscheint linear. Wenns noch nicht ganz passt, könnt ihr am Monitor ( wenn das der Monitor nicht bietet, benutzt die Einstellungsmöglichkeiten eures Grafikkartentreibers ) den Gammawert noch ein wenig korrigieren. &lt;br /&gt;
&lt;br /&gt;
Falls ihr gerne noch etwas mehr Zeit investieren wollt, danns schaut doch mal [http://tom.via.de/Fotoseiten/Kalibrierung/kalibrierung.asp hier] oder [http://de.wikipedia.org/wiki/Gammakorrektur#Gamma-Testgrafik hier] vorbei. Auf diesen und auf vielen anderen Seiten im Netz wird beschrieben, wie man seinen Monitor einstellen kann - meine Anleitung gehört doch eher zu den primitiven. Falls das Bild des Monitors jetzt eher grau und milchig erscheint, seid ihr wahrscheinlich dem Problem erlegen, daß unsere Augen logarithmische Farbveränderungen bevorzugen und lineare Verläufe eher ungewohnt sind - dann ist es Zeit, sich eine etwas genauere Beschreibung zum Thema Bildschirm-justierung/kalibrierung durchzulesen.&lt;br /&gt;
&lt;br /&gt;
== Physikalische und biologische Grundlagen ==&lt;br /&gt;
Physikalisch besteht Licht aus Wellen. Diese haben verschiedene Wellenlaengen und je nach Zusammensetzung entsteht der eine oder der andere Farbeindruck.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Farbspektrum.png|center]] &lt;br /&gt;
&lt;br /&gt;
Das sichtbare Licht hat Wellenlängen zwichen 400nm (Violett) bis 750 nm (Rot). Bei kürzeren Wellenlängen unter 400nm kommen dann Ultra Violette, Röntgen und schließlich Gamma Strahlen. Auf der anderen Seite über 750 nm folgen Infrarot, Mikrowellen, Funkempfang (LW, MW, UKW, ...), usw. Auf dem Monitor lassen sich nicht alle Reinfarben darstellen, seht das obige Bild also eher als Eindruck statt als &amp;quot;so siehts also aus&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Da unser Auge nur 3 Grundfarben unterscheiden kann (manche Menschen können sogar 4 Farben unterscheiden, wieder andere dagegen nur 2.), kann man verschiedene Farbeindrücke nicht nur durch verschiedene Wellenlängen erzeugen,  sondern auch durch das Mischen und Verlagern der Intensitäten einer Reihe von Grundfarben. So wird am Monitor  bekanntlich (additiv) mit Rot, Grün und Blau, auf Printmedien üblicherweise (subtraktiv) mit Cyan, Gelb, Magenta und Schwarz gemischt. Man kann so zwar nicht jede sichtbare Farbe mischen, aber doch so viele, daß ein guter Farbeindruck entsteht.&lt;br /&gt;
&lt;br /&gt;
== Verschiedene Farbräume ==&lt;br /&gt;
=== RGB ===&lt;br /&gt;
Der Rot, Grün, Blau Farbraum ist der Standardfarbraum für Computer und viele andere Bildschirmgeräte. Damit Farben aus anderen Farbräumen auf einem solchen Gerät dargestellt werden können, müssen sie immer zuerst auf diesen Farbraum umgerechnet werden. Er ist neben CMY einer der am wenigsten anschaulichen Farbräume. Farben lassen sich darin nur sehr schlecht identifizieren, sinnvolle Farbmanipulationen sind kaum möglich. Der Vorteil ist jedoch, daß die 3 Grundfarben etwa denen entsprechen, die auch auf unserer Netzhaut am besten erkannt werden - die Folge: höchst brilliante Farben, die einen großen Teil aller sichtbaren Farben abdecken. Den Farbraum kann man sich als drei dimensionalen Würfel am Nullpunkt vorstellen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_RGB.png|center]] &lt;br /&gt;
&lt;br /&gt;
Ausgehend vom Schwarz kann man nach rechts (Rot), nach oben (Grün) oder nach vorne (Blau) laufen und erhält immer hellere Farben. Schließlich gelangt man zum Weiß. Dazu gibt es auch eine weitere Veranschaulichung:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_RGB_additiv.png|center]] &lt;br /&gt;
&lt;br /&gt;
=== CMY ===&lt;br /&gt;
Der Cyan, Magenta, Gelb Farbraum ist dem RGB Farbraum sehr ähnlich. Allerdings ist er für Printmedien konzipiert. Ist keine Farbe aufgetragen, so erhält man den Hintergrund - meist ein weißes Blatt Papier. Je mehr man von einer Farbe aufträgt, desto weniger scheinen die anderen Farben durch - trägt man also alle Farben auf, bleibt vom ursprünglichen Weiß nichts über und man erhält Schwarz. Da jedoch der Hintergrund im Allgemeinen nicht leuchtet, können Farben nie derart hell erscheinen, wie im RGB Farbraum - man möge dies bei Druck-Anwendungen beachten:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_CYM.png|center]] &lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_CYM_subtraktiv.png|center]]&lt;br /&gt;
&lt;br /&gt;
Zum Umrechnen von RGB in CMY ist nicht viel nötig:&lt;br /&gt;
 R = 1-C&lt;br /&gt;
 G = 1-M&lt;br /&gt;
 B = 1-Y&lt;br /&gt;
Und umgekehrt:&lt;br /&gt;
 C = 1 - R&lt;br /&gt;
 M = 1 - G&lt;br /&gt;
 Y = 1 - B&lt;br /&gt;
&lt;br /&gt;
=== CMYK ===&lt;br /&gt;
Der CMYK Farbraum entspricht im wesentlichen dem CMY Farbraum, mit dem Unterschied, daß zusätzlich Schwarz zum Beimischen zur Verfügung steht. Dies kann beim Drucken von sehr dunklen Tönen hilfreich sein und spart ausserdem die teure Farbe. In manchen Fällen ist es sogar unumgänglich mit Schwarz zu drucken, wenn sich durch die anderen Druckfarben kein richtiges Schwarz erzeugen lässt (was häufig der Fall ist, u.a. auch bei den meisten Tintendruckern). &lt;br /&gt;
&lt;br /&gt;
Umrechnen CMYK nach CMY:&lt;br /&gt;
 CMY.C = C * ( 1 - K ) + K&lt;br /&gt;
 CMY.M = M * ( 1 - K ) + K&lt;br /&gt;
 CMY.Y = Y * ( 1 - K ) + K&lt;br /&gt;
&lt;br /&gt;
Umrechnen CMY nach CMYK&lt;br /&gt;
 CMYK.K = min(C,M,Y);&lt;br /&gt;
 if ( CMYK.K == 1 ) { &lt;br /&gt;
   CMYK.C = 0;   &lt;br /&gt;
   CMYK.M = 0;&lt;br /&gt;
   CMYK.Y = 0;&lt;br /&gt;
 } else {&lt;br /&gt;
   CMYK.C = (C-CMYK.K)/(1-CMYK.K);   &lt;br /&gt;
   CMYK.M = (M-CMYK.K)/(1-CMYK.K);   &lt;br /&gt;
   CMYK.Y = (Y-CMYK.K)/(1-CMYK.K);   &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== HSV ===&lt;br /&gt;
Der Hue, Saturation, Value (Farbton, Sättingung, Helligkeit) ist ein Farbraum, der sehr häufig im Einsatz ist. Da der Farbton als solches an einem Kanal zu identifizieren ist, werden viele Bildoperationen, die mit Farbe zu tun haben, in eben diesem Farbraum berechnet. Eine bildliche Vorstellung dieses Farbraums ist sehr viel einfacher, als die des RGB Farbraums. Wie also kann man sich ihn vorzustellen?&lt;br /&gt;
&lt;br /&gt;
Eine gute Möglichket ist als Zylinder. Die Unterseite ist schwarz. Bewegt man sich von der Mitte der Unterseite auf die gegenüberliegende Seite zu, wird es heller. Inmitten der hellen Seite ist Weiß. Geht man von dort nach aussen, erhöht sich die Farbsättigung. Geht man dann auf dem Kreis spazieren, bleibt Helligkeit und Sättigung konstant, während sich die Farbe ändert. Dieses Prinzip wird bei vielen Farbauswahldialogen angewendet (Im Beispiel: Paint.NET) :&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_HSV_auswahl1.png|center]] &lt;br /&gt;
&lt;br /&gt;
Der Kreis stellt die farbige Oberseite des Zylinders dar. Von der Mitte nach Aussen also die Sättigung, den Umfang entlang die Farbe. Der Balken beschreibt die Helligkeit. Sehr beliebt ist auch die aufgefaltete Variante (MS-Windows Standard Farbauswahl Dialog):&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_HSV_auswahl2.png|center]]&lt;br /&gt;
&lt;br /&gt;
Im quadratischen Feld ist von Links nach Rechts die Farbe, von Unten nach Oben die Sättigung aufgetragen. Der Balken gibt wieder die Helligkeit an. &lt;br /&gt;
&lt;br /&gt;
Es existieren noch viele verschiedene Varianten, die alle mehr oder weniger identisch funktionieren. Wir wollen es bei diesen zwei Beispielen belassen.&lt;br /&gt;
&lt;br /&gt;
Die Farbreihenfolge wird gewöhnlich definiert als Rot, Magenta, Blau, Cyan, Grün, Gelb, Rot. Zwischen den Vollfarben wird linear interpoliert, was zu folgenden Umrechnungen führt:&lt;br /&gt;
&amp;lt;cpp&amp;gt;&lt;br /&gt;
        // Based on C Code in &amp;quot;Computer Graphics -- Principles and Practice,&amp;quot;&lt;br /&gt;
        // Foley et al, 1996, p. 593.&lt;br /&gt;
        public static RGB HSVToRGB(double h, double s, double v)&lt;br /&gt;
        {&lt;br /&gt;
            double f, hTemp, p,q,t;&lt;br /&gt;
            int i;&lt;br /&gt;
            RGB Result = new RGB();&lt;br /&gt;
            if (s == 0) {&lt;br /&gt;
                //Achromatic&lt;br /&gt;
                Result.R = v;&lt;br /&gt;
                Result.G = v;&lt;br /&gt;
                Result.B = v;&lt;br /&gt;
                return Result;&lt;br /&gt;
            }&lt;br /&gt;
            if (h &amp;lt; 0)&lt;br /&gt;
                h = Math.PI * 2 - h;&lt;br /&gt;
       &lt;br /&gt;
            if (h &amp;gt; 2 * Math.PI)&lt;br /&gt;
                h = h - Math.Truncate(1.0 / (Math.PI * 2) *h)* (Math.PI * 2);&lt;br /&gt;
         &lt;br /&gt;
            hTemp = h / (2*Math.PI / 6);&lt;br /&gt;
            i = (int) Math.Truncate(hTemp);  // largest integer &amp;lt;= h&lt;br /&gt;
            f = hTemp - i;                   // fractional part of h&lt;br /&gt;
     &lt;br /&gt;
            p = v * (1.0 - s);&lt;br /&gt;
            q = v * (1.0 - (s * f));&lt;br /&gt;
            t = v * (1.0 - (s * (1.0 - f)));&lt;br /&gt;
              &lt;br /&gt;
            switch (i) {&lt;br /&gt;
                case 0: { Result.R = v; Result.G = t; Result.B = p; break; }&lt;br /&gt;
                case 1: { Result.R = q; Result.G = v; Result.B = p; break; }&lt;br /&gt;
                case 2: { Result.R = p; Result.G = v; Result.B = t; break; }&lt;br /&gt;
                case 3: { Result.R = p; Result.G = q; Result.B = v; break; }&lt;br /&gt;
                case 4: { Result.R = t; Result.G = p; Result.B = v; break; }&lt;br /&gt;
                case 5: { Result.R = v; Result.G = p; Result.B = q; break; }&lt;br /&gt;
            }&lt;br /&gt;
            return Result;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        // Based on C Code in &amp;quot;Computer Graphics -- Principles and Practice,&amp;quot;&lt;br /&gt;
        // Foley et al, 1996, p. 594.&lt;br /&gt;
        public static HSV RGBToHSV(double r, double g, double b)&lt;br /&gt;
        {&lt;br /&gt;
            HSV result = new HSV();&lt;br /&gt;
            double delta, min;&lt;br /&gt;
    &lt;br /&gt;
            min = Math.Min(r, Math.Min(g, b));&lt;br /&gt;
            result.v = Math.Max(r, Math.Max(g, b));&lt;br /&gt;
            delta = result.v - min;&lt;br /&gt;
        &lt;br /&gt;
            // Calculate saturation: saturation is 0 if r, g and b are all 0&lt;br /&gt;
            if (result.v == 0.0)&lt;br /&gt;
                result.s = 0;&lt;br /&gt;
            else&lt;br /&gt;
                result.s = delta / result.v;&lt;br /&gt;
   &lt;br /&gt;
            if (result.s == 0)&lt;br /&gt;
                result.h = 0; //Achromatic&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                if (r == result.v)&lt;br /&gt;
                {   //winkel zw. gelb/magenta&lt;br /&gt;
                    result.h = (g - b) / delta * (2 * Math.PI / 6.0);&lt;br /&gt;
                }&lt;br /&gt;
                else if (g == result.v)&lt;br /&gt;
                {    //zwischen cyan und gelb&lt;br /&gt;
                    result.h = (2 + (b - r) / delta) * (2 * Math.PI / 6.0);&lt;br /&gt;
                }&lt;br /&gt;
                else if (b == result.v)&lt;br /&gt;
                {// ...&lt;br /&gt;
                    result.h = (4 + (r - g) / delta) * (2 * Math.PI / 6.0);&lt;br /&gt;
                }&lt;br /&gt;
                if (result.h &amp;lt; 0)&lt;br /&gt;
                    result.h = result.h + 2 * Math.PI;&lt;br /&gt;
            }&lt;br /&gt;
            return result;&lt;br /&gt;
        }&lt;br /&gt;
&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== HSL ===&lt;br /&gt;
Der Hue Saturation Lightness Farbraum ist dem HSV Farbraum sehr ähnlich. Die Definition des Farbtons (Hue) ist identisch, lässt sich also auf die gleiche Weise berechnen. Die anderen Werte berechnen sich aus den RGB Werten wie folgt:&lt;br /&gt;
 MAX = max (R,G,B);&lt;br /&gt;
 MIN = min (R,G,B);&lt;br /&gt;
 &lt;br /&gt;
 L = (1.0/2.0) * (MAX + MIN);&lt;br /&gt;
 if (MIN == MAX) &lt;br /&gt;
 {&lt;br /&gt;
   S = 0&lt;br /&gt;
 } else if (L &amp;lt;= 1.0/2.0) {&lt;br /&gt;
   S = (MAX - MIN) / (2.0*L) &lt;br /&gt;
 } else {&lt;br /&gt;
   // entspr. Fall: L &amp;gt; 1.0/2.0&lt;br /&gt;
   S = (MAX - MIN) / (2.0-2.0*L)  &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Man stellt sich den HSV Farbraum gerne als Doppelkonus vor. Die obere Spitze ist weiß, die untere schwarz. Am Rand des Bauches befinden sich die Vollfarben, die zur Mitte hin an Sättigung verlieren (Bild: Wikipedia [EN]):&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Color_Cones.png|center]]&lt;br /&gt;
&lt;br /&gt;
=== LAB ===&lt;br /&gt;
Der LAB Farbraum ist einer an das menschliche Sehen angepasster Farbraum. Er umfasst alle vom Auge unterscheidbaren Farben und ein bischen mehr. Er dient dazu, Farbechtheit zu garantieren, was wichtig ist, wenn man z.B. am Bildschirm Bilder bearbeitet und diese am Ende drucken oder auf Fotopapier auslasern lassen möchte, so daß die Vorlage am Monitor dem entspricht, was auf dem Papier landen wird. Er dient dabei nur als Umrechnungsfarbraum, wobei auf die spezifischen Eigenschaften des jeweilig genutzen Gerätes geachtet werden muss.&lt;br /&gt;
&lt;br /&gt;
== Farbraumspaß ==&lt;br /&gt;
Wir wollen uns hier ein wenig mit den Möglichkeiten des HSV Farbraumes vertraut machen und einige Spielereien ausprobieren. &lt;br /&gt;
=== Vergrauen ===&lt;br /&gt;
Im HSV Farbraum kann man ein Bild sehr einfach in ein Graustufenbild umwandeln, indem man die Sättigung auf 0 stellt:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Rothsee_farbig.png|center]]&lt;br /&gt;
[[Bild:Farbräume_Rothsee_grau.png|center]]&lt;br /&gt;
&lt;br /&gt;
Wenn einem reines S/W zu langweilig ist, kann man auch ein feste Sättigung und Farbe vorgeben, so daß das Bild eingefärbt wird ( S/W-Foto-Material verändert häufig mit dem Alter ein wenig seine Farbe oder ist von vornherein leicht farbig ). Wer Spaß an dieser Art der Bildbearbeitung findet, kann auch noch die Helligkeit anpassen - Schwarzweißfilme sind nach Wellenlängen unterschiedlich empfindlich. Blau wird auf dem positiv häufig heller wiedergegeben als grün, welches wiederum heller als rot erscheint. Viel Spaß beim ausprobieren.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Rothsee_blackwhitestyle.png|center]]&lt;br /&gt;
&lt;br /&gt;
=== Farbkurven ===&lt;br /&gt;
Wer sich einmal mit einem Bildbearbeitungsprogramm auseinandergesetzt hat, wird sie kennen, die Dialoge zum Verändern der Farbkurven. Die Kurven stellen eine Verschiebungsfunktion dar: Hat man z.B. ein Farbkurve für den roten Farbkanal festgelegt, so beschreibt die Farbkurve f an einer Stelle i den Wert, den ein Punkte im roten Farbkanal hat, wenn er vorher den Wert i hatte, also:&lt;br /&gt;
 Punkt.rot = f(Punkt.rot);&lt;br /&gt;
im Bild: GIMP:&lt;br /&gt;
[[Bild:Farbräume_GIMPColorcurvesdialog.png|center]]&lt;br /&gt;
Diese Idee wollen wir uns zu Eigen machen - so ist es im HSV Farbraum nur zu konsequent, nicht Rot/Grün/Blau, bzw. Cyan/Magenta/Gelb sondern die Hue, Saturation und Value Werte zu manipulieren. Und die Sache ein wenig auf die Spitze zu treiben, wollen wir uns nicht nur mit Hue/Hue und den 2 anderen Kurven beschäftigen, sondern auch mit gemischten, bei denen sich anhand der Farbe die Helligkeit oder Sättigung ändert. Vieles ist hier denkbar.&lt;br /&gt;
&lt;br /&gt;
Um es realisieren zu können, benötigt man zuerst einmal eine eigene Dialogbox, die das Bearbeiten von (Farb-)Kurven zulässt. Im wesentlichen dürfte das Niemanden hier überfordern - ich empfehle folgende Szenerie: Die Kurve wird mithilfe von Spline-Interpolation erzeugt. Die Menge der Stützstellen ist im wesentlichen beliebig, für einige Kurven ist es jedoch wichtig, nicht nur natürliche, sondern auch periodische Kurven erzeugen zu können. Genauere Informationen hierzu finden sich in den Literaturangaben.&lt;br /&gt;
&lt;br /&gt;
Die einfachste Art der Kurven ist wie gesagt die, die sich selber beeinflussen. So lassen sich leicht Farben durch andere Farben tauschen, ohne den Rest der Farben zu beeinflussen. Man kann natürlich auch bestimmte Sättigungen hervorheben (also Sättigung/Sättigung statt bei Farben Hue/Hue) oder ähnliches. Als Beispiel wird der Hue-Bereich von Gelb in den von Rot verschoben. Durch feine Abstimmung lässt sich erreichen, daß andere Farben sich dabei nicht verändern (Diesen Effekt kann man noch leicht in Photoshop erreichen, man muss jedoch für jede Farbe getrennt vorgehen, falls man verschiedene Farben verändern möchte: Image/Adjustmennts/Hue-Saturations . Wir können dagegen leicht mehrere Farben auf einmal austauschen.).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Hue_Hue_mapping.png|center]]&lt;br /&gt;
&lt;br /&gt;
Als Alternative noch eine Sättigung/Sättigung Variante des obigen Bildes. Links wurde die 20. Wurzel aus der Sättigung gezogen, rechts wurde die Sättigung zur 4. Potenz erhoben (dies entspricht einer Erniedrigung bzw. Erhöhung des Sättigungkontrastes). Die einstellbaren Kurven lassen sich dazu natürlich genauso benutzen, aber so sparen wir uns ein paar Bilder ;-)&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Sat_Sat_mapping.png|center]]&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir einmal eine Value/Hue Variante betrachten. Ziel ist es, ein Pixel anhand seines Value den Hue weiterzudrehen. Man trägt im Kurvendialog wie folgt an: In Y-Richtung variiert die Hue, in X-Richtung ist Value von 0 bis 1 angetragen. Zu einer bestimmten Value soll also der Hue um einen bestimmten Winkel weitergedreht werden - vorwärts und rückwärtsdrehen sollte möglich sein. Rechnen könnte man dann:&lt;br /&gt;
&lt;br /&gt;
 Pixel.Hue = Pixel.Hue + Kurve(Pixel.Value);&lt;br /&gt;
&lt;br /&gt;
Da Pixel.Hue dadurch auch negative oder zu große Werte annehmen kann, sollte man sie wieder auf den Berech 0 bis 2*Pi zurückrechnen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Farbräume_Val_Hue_mapping.png|center]]&lt;br /&gt;
&lt;br /&gt;
Im obigen Bild ist die zugrundeliegende Kurve die [http://de.wikipedia.org/wiki/Glockenkurve Gaussche Glockenkurve] mit sigma = 0.29, mu = 0.9, d.h. also, daß bei niedrigen value Werten im wesentlichen keine Veränderung des Hue passiert. Je heller die Szene jedoch wird, desto stärker verschiebt sich der Farbton. Da die Lichtquelle im Hintergrund des Fotos ist, verändern sich die Farben stärker, je weiter hinten die Luftballons sich befinden.&lt;br /&gt;
&lt;br /&gt;
Es lassen sich noch einige weitere Varianten vorstellen, als die, die hier gezeigt wurden. So könnte man anhand einer Hue/Sat Kurve bestimmte Farben vergrauen lassen und andere hervorheben - der Effekt ist sicherlich nicht gänzlich unbekannt. In der Fotografie wird gerne entsprechend manipuliert: Man stelle sich ein Mädchen vor, daß eine rote Rose hält. Alle Farben sind grau, nur die Blüte der Rose ist rot - mit Hue/Sat Kurven ist das wirklich sehr leicht zu erreichen.&lt;br /&gt;
&lt;br /&gt;
== Literatur ==&lt;br /&gt;
* [http://www.efg2.com/Lab/Graphics/Colors/index.html Earl F. Glynn II: efg's Palettes and Colors Lab]&lt;br /&gt;
* [http://www.efg2.com/Lab/Library/Color/index.html Earl F. Glynn II: efg's Color Reference Library]&lt;br /&gt;
* [http://www.midnightkite.com/color.html Dan Bruton: Color Science]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Color_model Englische Wikipedia: Color Models. Viele informationen, Veranschaulichungen, Umrechnungsformeln]&lt;br /&gt;
* [http://www.adhocconference.com/cgi-bin/blosxom.cgi/PastShows/MacHack16/2001_papers.html Darrin Cardani: Adventures in HSV Space (als PDF)]&lt;br /&gt;
* [http://de.wikipedia.org/wiki/Spline-Interpolation Wikipedia: Spline interpolation]&lt;br /&gt;
* Bronstein, Semendjajew, Musiol, Mühlig: Taschenbuch der Mathematik. 5 Auflage. S.955: 19.7.1 Kubische Splines&lt;br /&gt;
* [http://www.arndt-bruenner.de/mathe/scripts/kubspline.htm Arndt Brünner: Kubische Splines]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=DGL_Projekte&amp;diff=16728</id>
		<title>DGL Projekte</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=DGL_Projekte&amp;diff=16728"/>
				<updated>2006-03-26T19:23:52Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Action */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=DGL Projects Corner=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
Willkommen in der '''[[DelphiGL|DGL]] Projekte Ecke'''!&lt;br /&gt;
&lt;br /&gt;
Auf dieser Seite findet ihr Projecte die von '''unseren Mitgliedern erstellt''' und als '''abgeschlossen''' gewertet wurden.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Spiele==&lt;br /&gt;
Viele, um nicht zu sagen die meisten, DGL-Mitglieder widmen sich dem Thema Spiele. Was dabei an respektablen Ergebnissen entstanden ist könnt ihr in dieser Rubrik sehen.&lt;br /&gt;
&lt;br /&gt;
===3D Shooter und Labyrinth Spiele===&lt;br /&gt;
&lt;br /&gt;
===Action===&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;30%&amp;quot;|Name&lt;br /&gt;
!width=&amp;quot;50%&amp;quot;|Beschreibung&lt;br /&gt;
!width=&amp;quot;20%&amp;quot;|Macher&lt;br /&gt;
|-&lt;br /&gt;
|[[Bild:Thumb_asteroids.jpg|framed|center|Link: '''[[Projekt_Asteroids|Asteroids]]''']]&lt;br /&gt;
&lt;br /&gt;
|Asteroids ist ein Remake des alten Klassikers &amp;quot;Comet&amp;quot;. Ziel des Spiels ist es so viel Asteroiden wie möglich zu zerstören und dadurch möglichst viele Punkte zusammeln. An einem Spiel können bes zu 4 Spieler gleichzeitig teilnehmen.&lt;br /&gt;
&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|[[Benutzer:Magellan|Magellan]]&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|[[Bild:Thumb_napalmbomber.jpg|framed|center|Link: '''[[Projekt_NapalmBomber3D|NapalmBomber3D]]''']]&lt;br /&gt;
&lt;br /&gt;
|NapalmBomber3D ist wie der Titel schon vermuten lässt ein 3D-Klon des bekannten Bombermanspielprinzips.Durch die Nutzung von OpenGL lässt sich das beliebte Spielprinzip recht einfach grafisch aufmotzen.&lt;br /&gt;
Neben dem Spiel gibt es natürlich auch noch einen Karteneditor mit dem sich in Windeseile eigenen Maps erstellen lassen.&lt;br /&gt;
&lt;br /&gt;
Neben inzwischen über 50.000 Downloads (im Schnitt sinds immernoch &amp;gt; 400 pro Monat) und diversen sehr guten Reviews hat es das Spiel sogar auf die PC-Action Ausgabe 07/2004 geschafft.&lt;br /&gt;
&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|[[Benutzer:Sascha Willems|Sascha Willems]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Brett- und Kartenspiele===&lt;br /&gt;
&lt;br /&gt;
===Geschicklichkeit===&lt;br /&gt;
&lt;br /&gt;
===Manager===&lt;br /&gt;
&lt;br /&gt;
===Simulationen===&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Thumb_asteroids.jpg&amp;diff=16727</id>
		<title>Datei:Thumb asteroids.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Thumb_asteroids.jpg&amp;diff=16727"/>
				<updated>2006-03-26T19:09:48Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: Thumb für Projekt_Asteroids&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Thumb für [[Projekt_Asteroids]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Projekt_Asteroids&amp;diff=16726</id>
		<title>Projekt Asteroids</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Projekt_Asteroids&amp;diff=16726"/>
				<updated>2006-03-26T18:44:31Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Projekt: Asteroids =&lt;br /&gt;
==Kurzbeschreibung==&lt;br /&gt;
Asteroids ist ein Remake des alten Klassikers „Comet“ für 1 bis 4 Spieler. Die Spieler können entweder über Netzwerk spielen oder sich eine Tastatur teilen, was den Spaßfaktor um Mengen erhöht. Es gibt vier verschiedene Spielmodi in denen die Spieler entweder gemeinsam oder gegeneinander antreten können. Ziel des Spiels ist es nach Möglichkeit nicht von Asteroiden zerlegt zu werden, sondern den Spieß umzudrehen.&lt;br /&gt;
&lt;br /&gt;
Im Programm kann der Spieler Effekte wie Partikelsysteme und dynamische Beleuchtung mit Hilfe des OpenGL-Lichtes bestaunen. Der Spieler kann anhand komplexer Menüs durch das Programm navigieren.&lt;br /&gt;
==Zusamnmenfassung der Projektentwicklung==&lt;br /&gt;
===Die Vorgeschichte===&lt;br /&gt;
Ursprünglich hatte ich vor - wahnsinnig wie ich bin - einen 3D-Weltraumshooter zu schreiben. &lt;br /&gt;
Dessen Entwicklung musste ich jedoch einstellen, da ich schnell feststellen durfte, dass sowohl künstliche Intelligenz als auch funktionierender Netzwerkcode nicht gerade leicht zu verwirklichen sind. Was bringt einem also der schönste Shooter, wenn man weder gegen menschliche Spieler noch gegen eine KI spielen kann, die wenigstens halbwegs intelligent erscheint. Daraufhin habe ich mir vorgenommen erstmal mit einem kleineren Projekt zu beginnen.&lt;br /&gt;
&lt;br /&gt;
Ich entschied mich ziemlich schnell für einen Comet-Clone, da hier sowohl KI als auch Multiplayermodus (z.B. an einem PC mit einer Tastatur) leichter zu verwirklichen sind. &lt;br /&gt;
Bei diesem Projekt habe ich mich vor allem auf den Spielspaß konzentriert und die Grafikpracht nur als Dreingabe betrachtet.&lt;br /&gt;
&lt;br /&gt;
Weiterhin verwendet dieses Programm keine speziellen Extensions, damit es auf so vielen Systemen wie möglich läuft.&lt;br /&gt;
&lt;br /&gt;
Für die Entwicklung des Programms kam Delphi und OpenGL zu Einsatz. Zur Soundausgabe habe ich  FMod verwendet. Die Tastatureingabe wird über die Win32-API gesteuert. Für den Netzwerkmodus wollte ich ursprünglich die Indy-Komponenten einsetzen. Allerdings bin ich damit auf einige Probleme gestoßen und habe mich daher für die Windows-Sockets entschieden. Unter anderem ließ sich das Programm mit den Windows-Sockets wesentlich besser debuggen.&lt;br /&gt;
===Die Entwicklung===&lt;br /&gt;
Die Entwicklung des Projektes erfolgte Schritt für Schritt. Das Grundspiel war schnell erstellt. Diverse Features wie eine Highscore, verschiedene Spielmodi, die Menüs und der Netzwerkmodus wurden von mir im nachhinein implementiert. Das hatte den Vorteil, dass das Programm von Beginn an spielbar war. Dies brachte jedoch leider auch Nachteile mit sich. So war beispielsweise die Implementation des Netzwerkmodus zu einem Hauptproblem geworden. Das Programm war von Anfang an nicht dafür ausgelegt worden. Nach zwei gescheiterten Versuchen einen Netzwerkmodus zum implementieren entschloss ich mich beim dritten Versuch das Spiel komplett neu zu schreiben. Das hat sehr viel Zeit gekostet und ich kann nur jedem empfehlen den Netzwerkmodus  (soweit geplant) von Anfang an zu integrieren und immer wieder zu testen, ob der Netzwerkcode auch das tut, was er soll.&lt;br /&gt;
&lt;br /&gt;
Auch die nachträgliche Integration der vier Spielmodi macht den Quellcode nicht gerade übersichtlicher und lässt ihn an einigen Stellen wie ein Flickwerk erscheinen. Meist unterscheiden sich die Modi nur in der Punkteverteilung, so dass eine nachträgliche Implementation recht einfach war. Wer aber Größeres vorhat, der sollte sich darüber vorher im klaren werden und sein Programm entsprechend auslegen. Generell gilt, dass eine nachträgliche Implementation von Features wesentlich mehr Zeit in Anspruch nimmt, als wenn man sich von Anfang an die Türen dafür offen gehalten hat. Ausnahmen bilden natürlich Dinge wie z.B. eine Highscore oder die Menüs.&lt;br /&gt;
&lt;br /&gt;
Da ich das Projekt sehr früh vorgestellt habe, kamen auch sehr viele gute Ideen aus der Community, die das Programm wesentlich verbessert haben und zu dem gemacht haben, was es heute ist.  Dazu zählen z.B. der dynamische Hintergrund, die Schilde der Spieler oder der zweite Asteroidentyp. Es gab noch wesentlich mehr gute Vorschläge. Hätte ich jedoch versucht alle Vorschläge umzusetzen würde ich Asteroids noch heute entwickeln.&lt;br /&gt;
&lt;br /&gt;
Durch die frühe Veröffentlichung standen eine Vielzahl an Systemen zur Verfügung, auf denen das Programm getetstet werden konnte und da die Tester selbst Programmierer waren konnten sie häufig sehr hilfreiche Fehlerbeschreibungen- teilweise sogar mit Lösungsvorschlägen liefern.&lt;br /&gt;
&lt;br /&gt;
Nach der Fertigstellung des Projektes habe ich ein [[Artikel_pm_asteroids|Postmortem]] veröffentlicht in dem ich den Entwicklungsprozess des Programms beschreibe und Probleme anspriche, die während der Entwicklung aufgetreten sind. Jeder Interessierte kann sich zudem den Delphi-Sourcecode des Spiels herunterladen. Anhand des Codes kann man sehr schön nachvollziehen, wie man ein etwas umfangreicheres Projekt aufbauen könnte. Ich hoffe sehr, dass der eine oder andere noch etwas daraus lernen kann.&lt;br /&gt;
==Links==&lt;br /&gt;
*[http://trinidad.delphigl.com Die Projektseite zu Asteroids]&lt;br /&gt;
*[http://www.delphigl.com/forum/viewtopic.php?t=2015 Der Projektthread im Forum]&lt;br /&gt;
*[[Artikel_pm_asteroids|Postmortem von Asteroids]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_1&amp;diff=16682</id>
		<title>Tutorial Lektion 1</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_1&amp;diff=16682"/>
				<updated>2006-03-18T17:11:23Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Die Initialisierung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Nicht zu weit aus dem Fenster lehnen =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Hallo,&lt;br /&gt;
in dem folgenden Tutorial möchte ich Euch etwas näher mit OpenGL vertraut machen. Der Großteil dieses Tutorials besteht aus bloßer Theorie, die jedoch absolut notwendig ist. Es ist nicht leicht über ein so trockenes Thema zu schreiben, denn in aller Regel sind Eure Erwartungen groß und wenn es schon keine aufwendige Grafikdemo wird, so wollt Ihr doch wenigstens ein Dreieck am Ende auf den Bildschirm gezaubert sehen. Seit nicht frustriert, wenn ich Euch nun verrate, dass das eigentliche Zeichnen (Rendern) erst im zweiten Tutorial behandelt wird. Ein leeres Fenster ist doch auch nicht zu unterschätzen oder ;)?&lt;br /&gt;
== Was ist (die) OpenGL? ==&lt;br /&gt;
Womit wir schon bei der ersten Frage wären. Ist es der, die oder das OpenGL. Um diese Frage zu beantworten müssen wir wissen, dass OpenGL ein Akronym für &amp;quot;Open Graphics Library&amp;quot; ist. Der englischen Begriff &amp;quot;Library&amp;quot; bedeutet Bibliothek, womit wir auf &amp;quot;die OpenGL&amp;quot; schließen. Häufig findet OpenGL aber auch ganz ohne Pronomen Verwendung. Nachdem wir diese Sache klargestellt haben kommen wir zur eigentlichen Frage zurück. Was ist OpenGL?&lt;br /&gt;
&lt;br /&gt;
OpenGL ist eine API, die es uns erlaubt relativ einfach Grafiken auf dem Bildschirm auszugeben ohne jedoch zu wissen, was im Hintergrund genau geschieht. Das ganze ist in gewisser Weise mit der Windows-API vergleichbar. Wir wissen zwar, wie man ein Fenster erzeugt, was im Hintergrund jedoch genau geschieht wissen wir nicht. &lt;br /&gt;
&lt;br /&gt;
Weiterhin ist OpenGL plattformunabhängig. Theoretisch könntet Ihr OpenGL also unter jedem Betriebssystem nutzen und Eure Programme würden auch auf jeder Hardware laufen. Dies bringt jedoch den Nachteil mit sich, dass bestimmte Dinge wie die Fensterverwaltung, Tastatur- oder Maussteuerung aus der Bibliothek ausgeschlossen sind, da diese sich von Betriebssystem zu Betriebssystem unterscheiden können. Um diese Dinge müssen wir uns also selbst kümmern. Zum Glück bietet uns die VCL (Visual Component Library) von Delphi ein mächtiges Werkzeug um solchen Herausforderungen entgegenzutreten.&lt;br /&gt;
&lt;br /&gt;
OpenGL selbst besitzt nur einen relativ kleinen Sprachumfang. Die wenigen Funktionen, die jedoch vielseitig einsetzbar sind lassen sich sehr leicht erlernen. Die folge hiervon ist aber auch, dass es keine Funktion zum Zeichnen komplexer Objekte wie z.B. die eines Vogels gibt. Solche Objekte muss man sich daher selbst aus den so genannten Primitiven, wie z.B. Punkten, Linien oder Dreiecken zusammensetzen.&lt;br /&gt;
&lt;br /&gt;
OpenGL ist ein riesiger Zustandsautomat. Je nachdem wie Ihr die einzelnen Zustände schaltet können die Bilder, welche ihr auf dem Bildschirm ausgebt völlig unterschiedlich aussehen. Beispielsweise sieht ein Würfel bei aktiviertem Licht gezeichnet wurde anders aus als derselbe Würfel ohne Licht. Verändert Ihr einmal einen Zustand wie z.B. die Farbe so werden sämtliche Primitive, die Ihr anschließend zeichnet mit dieser Farbe versehen, bis ihr die Farbe erneut wechselt.&lt;br /&gt;
&lt;br /&gt;
== Von Tausend und einer Funktion ==&lt;br /&gt;
 &amp;lt;pascal&amp;gt; glColor3b, glColor3d, glColor3f, glColor3i, glColor3s, &lt;br /&gt;
 glColor3ub, glColor3ui, glColor3us, glColor4b, glColor4d, &lt;br /&gt;
 glColor4f, glColor4i, glColor4s, glColor4ub, glColor4ui, &lt;br /&gt;
 glColor4us, glColor3bv, glColor3dv, glColor3fv, glColor3iv, &lt;br /&gt;
 glColor3sv, glColor3ubv, glColor3uiv, glColor3usv, &lt;br /&gt;
 glColor4bv, glColor4dv, glColor4fv, glColor4iv, glColor4sv, &lt;br /&gt;
 glColor4ubv, glColor4uiv, glColor4usv&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Es sind nicht ganz tausend und eine geworden, allerdings kommt dies schon sehr nahe dran ;). Sprach ich nicht gerade noch von einem kleinen Sprachumfang? Schnell werdet Ihr aber erkannt haben, dass das Grundgerüst dieser Funktion glColor heißt. All diese Funktionen verhalten sich gleich und unterscheiden sich lediglich in der Übergabe der Parameter. So werden bei glColor3i 3 Parameter vom Typ Integer erwartet. glColor4b verlangt hingegen 4 Parameter vom Typ Byte.&lt;br /&gt;
&lt;br /&gt;
Alle OpenGL-Funktionen besitzen den Präfix &amp;quot;gl&amp;quot; gefolgt von dem Befehlsstamm. Einige Funktionen besitzen noch einen Suffix, der den Typ oder auch die Anzahl der übergebenen Parameter wieder spiegelt. (siehe auch [[Funktions_Anhang|diese Erklärung]])&lt;br /&gt;
&lt;br /&gt;
OpenGL-Konstanten sind immer an ihren Großbuchstaben erkennbar und beginnen mit der Vorsilbe &amp;quot;GL_&amp;quot;. Obgleich Delphi keine Unterschiede zwischen Groß- und Kleinschreibung macht empfehle ich doch diese Schreibweise beizubehalten, denn sie steigert die Übersicht ungemein.&lt;br /&gt;
&lt;br /&gt;
== Wie sind OpenGL-Programme aufgebaut? ==&lt;br /&gt;
Um ein Dreieck zu rendern reicht es vielleicht das Bild einmal zu Zeichnen und auszugeben. Der Großteil von Euch wird sich jedoch nicht mit einem Dreieck zufrieden geben und möchte doch wenigstens Bewegungen und Animationen in seinen Programmen verwenden. Die Vorgehensweise ist so einfach wie genial: Um Bewegungen zu ermöglichen ist es notwenig, das Bild mehrmals zu zeichnen und auszugeben. Stellt Euch vor Ihr möchtet ein Dreieck von links nach rechts über den Bildschirm bewegen! Ihr zeichnet Euer Dreieck ganz links und gebt es aus. Noch bevor das menschliche Auge genug Zeit hat dieses Bild als einzelnes Bild zu deuten habt ihr dank der hohen Geschwindigkeit der heutigen PCs das Dreieck bereits um ein paar Pixel nach rechts verschoben und erneut gezeichnet. Ist Euer Rechner schnell genug, so erscheint den Betrachter die Bewegung als völlig flüssig und die eigentlichen Sprünge von wenigen Pixeln sind als solche nicht erkennbar. Das menschliche Auge kann etwa 25-30 Bilder pro Sekunde unterscheiden, also solltet Ihr immer versuchen mehr als 30 Bilder pro Sekunde (FPS = Frames per Second) zu zeichnen. &lt;br /&gt;
&lt;br /&gt;
Spätestens jetzt sollte Euch klar sein, warum es bei modernen Spielen manchmal ruckeln kann, wenn Euer Rechner zu langsam ist.&lt;br /&gt;
&lt;br /&gt;
Soweit zur Theorie. Wie aber realisiert man diesen Vorgang. Ganz klar: Wir zeichnen in einer Schleife. Nun stellt sich die Frage wie man dieses Problem elegant löst. Man könnte sich z.B. eine eigene Hauptprogrammschleife schreiben, in der man rendert. In dieser müsste man dann aber auch die Botschaften des Betriebssystems verarbeiten.&lt;br /&gt;
&lt;br /&gt;
Eine elegantere Lösung ist meiner Meinung nach das OnIdle-Ereignis der Anwendung hierfür zu nutzen. Wenn Ihr darin den Parameter &amp;quot;Done&amp;quot; auf &amp;quot;False&amp;quot; setzt wird diese Nachricht so oft ausgeführt, wie es nur irgendwie möglich ist. Das OnIdle-Ereignis wird im Hauptthread der Anwendung aufgerufen, was den positiven Nebeneffekt hat, dass die Nachrichten des Betriebssystems von der VCL verarbeitet werden und man die VCL in vollem Umfang nutzen kann.&lt;br /&gt;
&lt;br /&gt;
Nachteil der vorgestellten Methoden ist, dass die Anwendung nie zur Ruhe kommt, da die Schleife permanent durchlaufen wird. Damit steigt die Prozessorauslastung in der Regel auf 100%. Wenn man aus bestimmten Gründen in keiner echten Schleife rendern möchte könnte man sich auch mit einem Timer Abhilfe schaffen.&lt;br /&gt;
&lt;br /&gt;
== Die Initialisierung ==&lt;br /&gt;
Wer sofort loslegen möchte, den kann ich beruhigen, denn die Initialisierung von OpenGL ist mit unserem Header sehr einfach. Ihr müsst einfach bevor Ihr OpenGL nutzen möchtet, z.B. im OnCreate-Ereignis Eures Formulars die Funktion &amp;quot;InitOpenGL&amp;quot; aufrufen, nachdem Ihr die Unit &amp;quot;dglOpenGL&amp;quot; in Eurer Usesklausel eingebunden habt.&lt;br /&gt;
&lt;br /&gt;
Damit OpenGL auch weiß, wohin gezeichnet werden soll müssen wir ihr das irgendwie mitteilen. Hierfür ermitteln wir den Gerätekontext unseres Formulars mit Hilfe der Funktion &amp;quot;GetDC&amp;quot; und dem Handle unseres Formulars.&lt;br /&gt;
&lt;br /&gt;
Anschleißend erstellen wir einen Zeichenkontext mit Hilfe der Funktion &amp;quot;CreateRenderingContext&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nachdem wir diesen erstellt haben müssen wir Ihn noch aktivieren. Dies geschieht mit der Funktion &amp;quot;ActiveRenderingContext&amp;quot;. Das ganze sieht dann in etwa so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;var&lt;br /&gt;
  DC, RC:HDC;&lt;br /&gt;
procedure TfrmMain.FormCreate(Sender: TObject);&lt;br /&gt;
begin&lt;br /&gt;
  DC:=GetDC(Handle);&lt;br /&gt;
  RC:=CreateRenderingContext(DC, [opDoubleBuffered], 32, 24, 0, 0, 0, 0);&lt;br /&gt;
  ActivateRenderingContext(DC, RC);&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Prinzip könntet Ihr nun loslegen. Wenn Ihr Euer Bild nun im OnIdle-Ereignis zeichnet werdet Ihr schnell feststellen, dass Ihr nichts zu sehen bekommt. Das ist auch ganz normal, denn Ihr müsst das Bild auch noch ausgeben. Das geschieht mit Hilfe der Funktion &amp;quot;SwapBuffers&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Da wir sauber programmieren wollen müssen wir den Renderingkontext und den Gerätekontext wieder freigeben, wenn wir unser Programm beenden oder aber OpenGL nicht mehr benötigen. Die Funktionen &amp;quot;ReleaseDC&amp;quot; und &amp;quot;DestroyRenderingContext&amp;quot; erfüllen diese Aufgaben.&lt;br /&gt;
&lt;br /&gt;
Jetzt müssen wir nur noch die Größe des Bildes, welches wir rendern möchten definieren. Mit dem Befehl [[glViewport]] definieren wir die Zeichenfläche. Im Gegensatz zu Windows liegt der Ursprung bei OpenGL unten links. Da die Größe unserer Zeichenfläche der des Fensters entsprechend soll rufen wir diesen Befehl im OnResize-Ereignis unseres Formulars auf:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glViewport(0, 0, ClientWidth, ClientHeight);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die vier kommenden Zeilen solltet Ihr ganz schnell wieder aus Eurem Gedächtnis streichen und erst einmal als gegeben hinnehmen. In Tutorial 2 und 3 werden wir näher darauf eingehen. Soviel sei jedoch gesagt: Es wird nichts weiter unternommen als unsere dreidimensionale Welt aufzuspannen. Damit ist sichergestellt, dass Objekte in großer Entfernung kleiner erscheinen, so wie wir es gewohnt sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glMatrixMode(GL_PROJECTION);&lt;br /&gt;
glLoadIdentity;&lt;br /&gt;
gluPerspective(60, ClientWidth/ClientHeight, 0.1, 100);&lt;br /&gt;
glMatrixMode(GL_MODELVIEW);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit diesem Wissen könnt Ihr nun direkt in Tutorial 2 einsteigen.&lt;br /&gt;
&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Genug dazu. Ich freue mich sehr, dass Ihr Euch die Zeit genommen habt, dieses Tutorial zu lesen und OpenGL lernen wollt. Ich hoffe, dass wir die nächsten Tutorials genauso gut durchbekommen und dass am Ende jeder etwas gelernt hat und die Zeit nicht total vergebens war. Ich schreibe sicherlich nicht immer alles auf dem direktesten Weg, sondern rede gerne mal um den Brei herum. Wer das nicht mag, soll sich die OpenGL-Dokumentation zu Herzen nehmen, dort ist alles kurz und schmerzlos beschrieben ;). Für alle, die es nicht so trocken mögen, ist mein Schreibstil hoffentlich eine gute Alternative ;).&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Magellan'''&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_quickstart]]|[[Tutorial_lektion2]]}}&lt;br /&gt;
[[Kategorie:Tutorial|Lektion1]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Team&amp;diff=16238</id>
		<title>Team</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Team&amp;diff=16238"/>
				<updated>2006-02-09T21:43:04Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Moderatoren */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Vorwort =&lt;br /&gt;
&lt;br /&gt;
Auf dieser Seite befindet sich eine Auflistung der Personen, die momentan aktiv daran arbeiten, dass DGL Euch wie gewohnt im Netz mit Informationen versorgt. Bitte beachtet, dass die meisten der Personen nur einen begrenzten Vorrat an Zeit haben. Überlegt daher bitte sorgsam, an wen Ihr Euch wendet.&lt;br /&gt;
&lt;br /&gt;
= Das Team im Ganzen =&lt;br /&gt;
In diesen Abschnitt ist aufgelistet '''wer''' bei [[DelphiGL]] Verantwortung für einen Teil übernommen hat, und '''was''' genau er macht.&lt;br /&gt;
== Moderatoren ==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;20%&amp;quot;|Forumsname&lt;br /&gt;
!width=&amp;quot;30%&amp;quot;|Email&lt;br /&gt;
!width=&amp;quot;50%&amp;quot;|Aufgabenbereich&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Phobeus|Phobeus]] &lt;br /&gt;
|{{eMail|Phobeus|delphigl.com}}&lt;br /&gt;
|&lt;br /&gt;
*Technische Pflege des Wikis (Wartung/Updates)&lt;br /&gt;
*Betreuung der Hardware&lt;br /&gt;
*&amp;quot;der Chef&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Flash|Flash]] &lt;br /&gt;
|{{eMail|Flash|delphigl.com}}&lt;br /&gt;
|&lt;br /&gt;
*Inhaltliche Pflege des Wikis&lt;br /&gt;
*DGL-Poll pflegen&lt;br /&gt;
*News eintragen&lt;br /&gt;
*allgemeine Inhaltliche Kontrolle im Forum&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Nico Michaelis|Nico Michaelis]] &lt;br /&gt;
|{{eMail|delphic|delphigl.com}}&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Magellan|Magellan]] &lt;br /&gt;
|{{eMail|Magellan|delphigl.com}}&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Gruppen =&lt;br /&gt;
In diesem Teil findet ihr detailierte Informationen, wer für welchen Bereich zuständig ist.&lt;br /&gt;
== DGLSDK ==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;20%&amp;quot;|Forumsname&lt;br /&gt;
!width=&amp;quot;30%&amp;quot;|Email&lt;br /&gt;
!width=&amp;quot;50%&amp;quot;|Aufgabenbereich&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Flo|Flo]]&lt;br /&gt;
|{{eMail|Flo|DelphiGL.com}}&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:I0n0s|i0n0s]] &lt;br /&gt;
|{{eMail|JonasScholz|web.de}}&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== DGLOpenGL.pas ==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;20%&amp;quot;|Forumsname&lt;br /&gt;
!width=&amp;quot;30%&amp;quot;|Email&lt;br /&gt;
!width=&amp;quot;50%&amp;quot;|Aufgabenbereich&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Webseite ==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;20%&amp;quot;|Forumsname&lt;br /&gt;
!width=&amp;quot;30%&amp;quot;|Email&lt;br /&gt;
!width=&amp;quot;50%&amp;quot;|Aufgabenbereich&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Phobeus|Phobeus]] &lt;br /&gt;
|{{eMail|Phobeus|delphigl.com}}&lt;br /&gt;
|&lt;br /&gt;
*Technische Pflege des Seite (Wartung/Updates)&lt;br /&gt;
*Coding (Integrieren von Neuerungen)&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Flash|Flash]] &lt;br /&gt;
|{{eMail|Flash|delphigl.com}}&lt;br /&gt;
|&lt;br /&gt;
*DGL-Poll pflegen&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Wiki ==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable_B1}}&lt;br /&gt;
!width=&amp;quot;20%&amp;quot;|Forumsname&lt;br /&gt;
!width=&amp;quot;30%&amp;quot;|Email&lt;br /&gt;
!width=&amp;quot;50%&amp;quot;|Aufgabenbereich&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Flash|Flash]] &lt;br /&gt;
|{{eMail|Flash|delphigl.com}}&lt;br /&gt;
|&lt;br /&gt;
*Inhaltliche Pflege des Wikis&lt;br /&gt;
*Koordinierung&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:Phobeus|Phobeus]] &lt;br /&gt;
|{{eMail|Phobeus|delphigl.com}}&lt;br /&gt;
|&lt;br /&gt;
*Technische Pflege des Wikis (Wartung/Updates)&lt;br /&gt;
*Betreuung der Hardware&lt;br /&gt;
|-&lt;br /&gt;
|[[Benutzer:La Boda|La Boda]]&lt;br /&gt;
|{{eMail| -pdl-|web.de}}&lt;br /&gt;
|&lt;br /&gt;
*Inhaltliche Pflege des Wikis&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Benutzer:Magellan&amp;diff=16237</id>
		<title>Benutzer:Magellan</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Benutzer:Magellan&amp;diff=16237"/>
				<updated>2006-02-09T21:39:11Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Steckbrief =&lt;br /&gt;
Name: Frank Herrlich&lt;br /&gt;
&lt;br /&gt;
Nick: Magellan&lt;br /&gt;
&lt;br /&gt;
Geb: 1986&lt;br /&gt;
&lt;br /&gt;
Wohnort: Dresden&lt;br /&gt;
&lt;br /&gt;
Tätigkeit: Informatikstudent&lt;br /&gt;
&lt;br /&gt;
= Allgemein =&lt;br /&gt;
Ich gehöre eher zu den zurückhaltenden, schüchternen Mitgliedern der Community, die in ihren Kämmerlein bereits an DOOM8 werkeln, damit sie auch wirklich fertig sind, wenn Carmack die anderen 4 veröffentlicht hat ;).&lt;br /&gt;
&lt;br /&gt;
= Werdegang =&lt;br /&gt;
Bei mir hat alles mit einem Buch über Turbo Pascal angefangen. Die Grundlagen habe ich  anhand dieses Buches gelernt. Nur leider waren textbasierte Hello-World-Programme so ziemlich alles was ich damit hinbekam und die paar Linien und Striche, die ich mit Turbo Pascal auf den Bildschirm zaubern konnte rissen auch niemandem vom Hocker. Damit will ich aber auch nicht behaupten, dass das heute anders ist ;). Ich kann von Glück reden, dass in diesem Pascalbuch eine Version von Delphi 1 enthalten war. Ziemlich schnell versetzte mich Delphi in den Glauben man könnte damit die Welt retten :). Nachdem ich unzählige Programme geschrieben hatte, die sowieso niemand braucht trat ein Wandel in mein Leben. Das Internet!&lt;br /&gt;
&lt;br /&gt;
Ziemlich schnell entdeckte ich eine Seite, die sich mit dem Namen &amp;quot;Delphi OpenGL Community&amp;quot; schmückte. Nachdem ich die Tutorials intensiv studiert hatte und feststellte, dass ich das Forum auch nach Monaten noch besuchte entschied ich mich den gefährlichen Schritt zu wagen und mich erstmals im Internet zu registrieren ;).&lt;br /&gt;
Seither gehören Linien und Polygone zu meinen Altagsgegenständen und ich zerbreche mir eher den Kopf darüber, wie es meinem Nachbar möglich war, seinen Hund derart realistisch zu texturieren.&lt;br /&gt;
&lt;br /&gt;
Vor etwa einem Jahr habe ich begonnen mit C# fremdzugehen und mit der Zeit Delphi mehr und mehr den Rücken zugekehrt. Inzwischen arbeite ich nur noch mit C# und ich bin immernoch so verliebt wie am ersten Tag :).&lt;br /&gt;
&lt;br /&gt;
OpenGL bin ich aber weiterhin treu geblieben und das wird wohl auch so bleiben.&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15376</id>
		<title>Tutorial Lektion 4</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15376"/>
				<updated>2005-12-13T20:38:02Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Texturen richtig zubereitet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Texturen, Tapeten und Ihre Tücken=&lt;br /&gt;
&lt;br /&gt;
==Vorwort==&lt;br /&gt;
Hi Leute,&lt;br /&gt;
kaum zu glauben aber wahr. Dieses Tutorial wird ausnahmsweise mal etwas mehr Erholung sein. Zumindest am Anfang. Was wir bisher erreicht haben ist ja alles schön, nett, praktisch und auch wichtig als Grundlage aber wenn wir aus dem Fenster sehen hören wir die Vöglein zwitschern. Hö? Wir hören was sehend? Es ist tiefste Nacht? Es muss Frühling sein ^__^.&amp;lt;br&amp;gt;&lt;br /&gt;
Und was macht man da normalweise? Wir kramen herum und machen einen großen Frühjahrsputz... die Schränke abziehen und alles schön sauber und ordentlich machen. Hach... es dürstet mich richtig danach... :D (means... *würg*).&amp;lt;br&amp;gt;&lt;br /&gt;
Da unsere Tutorials bisher Gott sei Dank keine dreckige Sache waren werden wir das mit dem Saubermachen einfach mal wegfallen lassen und uns nur mit einem Tapetenwechsel begnügen. In der Tat werden wir ab jetzt unseren Tutorials mehr grafisches Gewicht zumuten. Endlich haben die blauen Dreiecke ein Ende! Ich wünsche Euch viel Spaß ;).&lt;br /&gt;
&lt;br /&gt;
==Crash-Kurs im Handwerk des Tapezierens==&lt;br /&gt;
&lt;br /&gt;
===Ich verstehe nur &amp;quot;Renovierung&amp;quot;?===&lt;br /&gt;
Ich finde es immer wieder erschreckend Leute im Internet zu treffen, die nicht wissen was eine Textur ist... ich meine, kennen keinen Kafka, keine Quantenphysik und wissen nicht einmal wo man die Systemsteuerung findet. Wie soll man solch einem Menschen erklären, was eine Textur ist?&lt;br /&gt;
Nun, am Besten fangen wir mit einem möglichst praktischen Beispiel an. Texturen sind wie... Tapeten. Wir blicken nun zu unserer linken Seite. Der Autor erwartet nun ein DirectMind-Uplink zum Empfangen der visuellen Bildsignale. Dort haben wir eine schöne Wand... quadratisch in ihrer Form. Wollen wir diese mit einer Tapete verzieren, gehen wir in den nächsten Baumarkt, suchen uns eine hübsche aus und bringen diese an der Wand an. Natürlich haben wir eine Große geholt, und fangen nicht mit kleinen Streifen an.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn dann alles geklappt hat stehen wir vor dieser Wand und begutachten die Tapete in voller Pracht direkt vor uns. Wir haben die Wand texturiert. Streng genommen machen wir auch bei OpenGL nichts anderes, als ein Bild zu laden und dieses auf eine Fläche zu kleben. Wir werden uns jedoch auf Dauer nicht damit begnügen immer nur quadratische Flächen zu texturieren, sondern durchaus auch mal Dreiecke oder andere Vielecke. Und auch hat man uns Werkzeuge in die Hand gegeben um diese Textur noch nachträglich an der Wand zu verschieben ohne dass wir sie abnehmen müssen. Ist doch super. Es lebe die virtuelle Welt!&lt;br /&gt;
&lt;br /&gt;
===Tapezieren leicht gemacht!===&lt;br /&gt;
Okay, wir haben lange genug um den heißen Brei herumgeredet und sollten uns nun endlich auf die Arbeit stürzen. Jeder von uns sollte in der Lage sein, ein Quadrat in OpenGL genau vor unserer Nase zu erzeugen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_nonetex.gif|thumb|256px|left|Leeres Quadrat]]&lt;br /&gt;
Spätestens nun sollte die gleiche Frage aufkommen, wie bei jedem, der zum ersten Mal versucht, eine Tapete an die Wand zu bringen: &amp;quot;Wie rum muss ich das Ding da befestigen?&amp;quot;. Immerhin müssen wir uns nicht um den Leim kümmern, das erledigt unsere Grafikkarte bzw. OpenGL für uns ;).&lt;br /&gt;
&lt;br /&gt;
Wer noch nie 3D programmiert hat wird im ersten Moment vielleicht fälschlicherweise denken, dass man die Position der Textur per Weltkoordinaten definiert. Das hätte allerdings fatale Folgen sobald sich das Objekt im Raum bewegt. Wir müssten die Position jedes mal neu berechnen. Um eben dieses Problem zu umgehen, geht man in der 3D-Programmierung einen anderen Weg. Man vergibt einfach für jede Ecke eines Objektes eine Koordinate der Textur. OpenGL errechnet dann aus diesen Texturkoordinaten das Stück der Textur, das dann über das gesamt Objekt projiziert wird.&lt;br /&gt;
&lt;br /&gt;
Die Rede ist hierbei vom so genannten UV-Mapping, welches vor allem bei Anfängern ein leichtes Gefühl des Unbehagens auslösen sollte. Es ist jedoch nur halb so wild, wenn man es halbwegs verstanden hat.&lt;br /&gt;
&lt;br /&gt;
Betrachten wir gleich mal folgendes Bild und versuchen, uns in die Problematik hineinzuversetzen. Da Texturen unterschiedliche Größen haben können wurden so genannte Texturkoordinaten eingeführt. Es ist total egal wie groß eine Textur ist, da sie nur einen Wertebereich von 0 bis 1 haben kann. Das heißt, wenn eine Textur 256x256 groß ist und eine andere 512x512, so haben beide eine maximale Größe von 1. Wir brauchen also das UV-Mapping nicht verändern, selbst wenn ein Objekt eine neue Textur mit anderer Größe erhält.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Auf diesem Bild sehen wir zum einen die Textur, die wir verwenden wollen, zum anderen das Objekt, auf das &amp;quot;geklebt&amp;quot; werden soll. Natürlich sieht das in der Realität nicht so aus. Ich denke aber diese Darstellung erleichtert das Verstehen ;).&lt;br /&gt;
&lt;br /&gt;
Die untere linke Ecke der Textur trägt die Texturkoordinaten von (0 / 0) (d.h. u = 0 und v = 0), die obere linke Ecke (0 / 1), die obere rechte Ecke (1 / 1) und schließlich die untere rechte Ecke die Koordinaten (1 / 0). Das heißt alles was wir machen müssen um auf unser Objekt eine Textur zu kleben ist dem jeweiligen Eckpunkt unseres Quadrates die entsprechende Texturkoordinate zuzuweisen. Wobei in diesem Sinne korrekt in Anführungszeichnen stehen sollte. Es gibt kein falsches UV-Mapping. Man kann tolle Sachen mit diesen Textur-Koordinaten machen und so z.B. auch eine Textur auf einem Objekt spiegeln. Dafür müssten wir in unserem Beispiel nur die linken und rechten UV-Mapping vertauschen und z.B. für den zweiten Punkt die Koordinaten von (1 / 1) setzen und dafür beim dritten (0/ 1). Genauso würden wir auch die unteren vertauschen. Die UV-Koordinaten, wie sie oben angegeben sind bewirken nur, dass die Textur, so wie sie in der Datei vorkommt auch auf das Objekt geklebt wird. Selbstverständlich ist es auch möglich eine Textur gekachelt aufzukleben indem Ihr Texturkoordinaten &amp;gt; 1 vergebt. Ebenso ist es möglich nur Teile einer Textur zu verwenden. Spielt ruhig ein wenig damit herum und schaut Euch an was passiert! Auf einige tolle Spielereien kommen wir zum Schluss noch mal zurück :).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv_02.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Sicherlich brennt es einigen von Euch nun bereits unter den Finger und Ihr fragt &amp;quot;Wie kann ich denn die UV-Koordinaten den Eckpunkten der Fläche zuweisen?&amp;quot;. Nun, zunächst funktioniert das ähnlich wie bei allen Dingen unter OpenGL. Wir setzen eine UV-Koordinate und solange wir nichts verändern werden alle Punkte mit diesen Koordinaten versehen bis wir andere Instruktionen geben. In unserem Fall müssen wir dies natürlich nach jedem Punkt machen. Die Funktion, die dafür verwendet wird heißt [[glTexCoord]]. Um also eine Textur auf unserem Quad zu projizieren, benötigen wir folgenden Code:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;!-- Zeilenumbrüche sind drinnen damit das Bild nicht die Code-Boc verunstaltet --&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(0,0); glVertex3f(-1,-1,0);&lt;br /&gt;
  glTexCoord2f(0,1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(1,1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(1,0); glVertex3f(1,-1,0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das klappt doch wunderbar oder? Damit wir die Textur aber auch wirklich genießen können müssen wir Texturing mit Hilfe von glEnable und dem Token GL_TEXTURE_2D aktivieren. Mit Hilfe von glDisable und demselben Token ist es dann auch möglich Objekte zu Zeichnen, die über keine Texturen verfügen. Andernfalls würde nämlich die zuletzt gesetzte Textur und die Texturkoordinaten des letzten glTexCoord-Aufrufs verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Doch eine Kleinigkeit habe ich Euch nun doch noch verschwiegen! Wir müssen natürlich noch die richtige Textur setzen damit OpenGL überhaupt weiß, was auf diesem Quad gezeichnet werden soll. Dies ist an sich noch relativ einfach, allerdings müssen wir diese auch noch in den Speicher bekommen, damit sie überhaupt zur Verfügung steht. Nun wird's theoretisch ;).&lt;br /&gt;
&lt;br /&gt;
===Tapeten besorgen===&lt;br /&gt;
Ich werde jetzt nicht näher darauf eingehen, wie man Texturen erstellt. Vielleicht gibt's ja einige Photoshopexperten unter Euch, die Lust haben einige Ihrer Tricks den anderen in Form eines Tutorials zu zeigen.&lt;br /&gt;
&lt;br /&gt;
Zunächst einmal müssen wir uns die eigentlichen Bilddaten besorgen. Wir werden das jetzt in diesem Tutorial mit [[SDL]] machen es gibt jedoch auch die Möglichkeit die Daten manuell zu laden das könnt Ihr hier nachlesen:&lt;br /&gt;
* [[TGA Bilder laden]]&lt;br /&gt;
Es gibt allerdings auch Texturloader die Euch die nächsten Kapitel abnehmen und das alles für Euch machen. glBitmap ist so ein Loader. Mehr dazu erfahrt Ihr in dem [[Glbitmap_loader|glBitmap]]-Artikel.&lt;br /&gt;
&lt;br /&gt;
Bei SDL rufen wir nur [[IMG_Load]] auf und prüfen dann ob das Laden erfolgreich war. Hierbei sei erwähnt, dass es unter Linux zu Problemen führen kann, wenn ein Programm nicht aus einer Konsole heraus gestartet wurde. In diesem Fall sind die Pfade zu den Texturen nämlich falsch gesetzt und das Laden würde fehlschlagen. Abhilfe schafft man durch das Verwenden von absoluten Pfaden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;uses SDL, SDL_Image;&lt;br /&gt;
&lt;br /&gt;
var &lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load(ExtractFileDir(paramStr(0))+'/wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das war es dann auch schon... Wir haben die Textur im Speicher. Doch was nun?&lt;br /&gt;
&lt;br /&gt;
===Texturen richtig zubereitet===&lt;br /&gt;
Nachdem sich unsere Textur nun im Speicher des Computers befindet, geht es darum daraus auch eine richtige Textur zu machen, damit wir diese in OpenGL anzeigen können. Bisher befinden sich ja nur die Rohdaten im Speicher. Hierfür teilen wir OpenGL mit, dass wir eine neue Textur erzeugen wollen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glGenTextures(1, @TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TexID ist in diesem Fall ein gluInt, kann aber genauso gut ein Array davon sein, um mehrere Texturen zu erzeugen. Genau dafür wird dann auch der erste Parameter verwendet, der OpenGL mitteilt wieviele Texturen in dieses Array geschrieben werden sollen. In unserem Fall ist dies eben nur ein Element. Aber was ist ist das für ein Wert in TexID? OpenGL verwaltet die Texturen anhand eindeutiger Namen. [[glGenTextures]] ermittelt einen oder mehrere bisher ungenutzte Namen und schreibt diese in TexID. Durch TexID können wir unsere Textur ab sofort also eindeutig identifizieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBindTexture(GL_TEXTURE_2D, TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir teilen OpenGL mit, dass sich von nun an alle Änderungen und Anweisungen, die sich auf Texturen beziehen auf die Textur TexID beziehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die folgenden beiden Zeilen sind zwar nicht wirklich nötig, um eine Textur zu erzeugen aber glaubt mir, sie werden ansonsten potthässlich aussehen. Wir werden in einem anderen Tutorial näher auf dessen Bedeutung eingehen, nämlich den so genannten Texturfiltern. Die momentane Einstellung ist leicht rechenlastig jedoch auch von recht guter Qualität. Ihr werdet anfangs keine Probleme mit der Geschwindigkeit bekommen ;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu guter Letzt müssen wir die Bildinformationen irgendwie an OpenGL übergeben. Dies übernimmt die Funktion [[glTexImage2D]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Parameter steht für den Typ der Textur. Die Dimension des Typs muss hier mit der des Befehls übereinstimmen (glTexImage2D erlaubt also nur GL_TEXTURE_2D). Der zweite Parameter gibt die Nummer des Level of Detail (LoD) an. Für den Anfang reicht hier der Level 0. Der dritte Parameter gibt an, wie viele Farbkomponenten in dem Bild enthalten sind (1-4). Die zwei folgenden Parameter übermitteln OpenGL die Breite und die Höhe des Bildes. Der sechste Parameter gibt die Breite des Rahmens an. Im siebenten Parameter wird das Format verlangt, in welcher Reihenfolge die einzelnen Farbkomponenten gespeichert sind. Der Typ, der einzelnen Farbwerte muss im 8. Parameter angegeben werden. Letztendlich müssen im 9. Parameter nur noch die Bildpunkte selbst übergeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit Hilfe dieser Funktion sollten nur Texturen der Größe 2^n x 2^n erzeugt werden. Andernfalls werdet Ihr die Textur nicht in Ihrer vollen Schönheit, d.h. überhaupt nicht betrachten können. Es gibt jedoch Möglichkeiten Texturen zu laden, die nicht die Größe 2^n entsprechen. Die Funktion [[gluBuild2DMipmaps]] bietet hier beispielsweise eine Alternative.&amp;lt;br&amp;gt;&lt;br /&gt;
Das war es auch schon. Wer mehr über die einzelnen Parameter und Befehle wissen will ist herzlich eingeladen in unserem Wiki umherzustöbern und sein Wissen zu erweitern um später selbst vielleicht einmal ein paar Artikel im Wiki zu veröffentlichen.&lt;br /&gt;
&lt;br /&gt;
Die Daten im Arbeitsspeicher brauchen wir nun nicht mehr. Bei SDL geben wir sie so frei:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;SDL_FreeSurface(tex);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fassen wir das ganze bei SDL nochmal zusammen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;var&lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load('./wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin		&lt;br /&gt;
    glGenTextures(1, @texture);&lt;br /&gt;
    glBindTexture(GL_TEXTURE_2D, texture);&lt;br /&gt;
		&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
		&lt;br /&gt;
    // Achtung! Einige Bildformate erwarten statt GL_RGB, GL_BGR. Diese Konstante fehlt in den Standard-Headern&lt;br /&gt;
    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&lt;br /&gt;
&lt;br /&gt;
    SDL_FreeSurface(tex);&lt;br /&gt;
  end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kommt aber bitte nicht auf die Idee die Textur in euerer Hauptschleife wieder und wieder neu zu laden. Es reicht die Textur einmal zu laden und von da an steht sie einem solange zur Verfügung bis man gedenkt sie wieder aus dem Grafikkartenspeicher zu entfernen.&amp;lt;br&amp;gt;&lt;br /&gt;
Das übernimmt die Funktion [[glDeleteTextures]]. glDeleteTextures funktioniert ähnlich wie glGenTextures, nur dass die Texturen entfernt werden. Der erste Parameter gibt die Anzahl der zu löschenden Texturen an, während der zweite Parameter den Namen der Textur bzw. ein Array der Namen mehrerer Texturen verlangt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das ist doch für den Anfang nicht schlecht. Ihr solltet nun in der Lage sein, zumindest einfache Objekte zu texturieren. Das ist eigentlich das gesamte Grundprinzip. Natürlich gestaltet es sich schwieriger ein komplexeres Objekt mit UV-Koordinaten zu versehen als ein Quad. An der Technik selbst ändert sich aber nur wenig. Wir werden nun einige Spielereien zeigen, die man mit Texturen machen kann damit Ihr ein Gefühl dafür bekommt, wie man ein Problem elegant umschiffen kann!&lt;br /&gt;
&lt;br /&gt;
==Die Rückkehr der Matrizen==&lt;br /&gt;
===Texturen===&lt;br /&gt;
Tja... und da ich ein Sadist bin [Anm. des Lektors: Ooooh ja!] werden wir uns nun nochmals den Matrizen zuwenden! Dachtet Ihr etwa, Ihr seid die Dinger schon wieder los? Ich habe Euch im letzten Tutorial angedroht, dass es nicht nur eine Matrix für die &amp;quot;Welt&amp;quot; gibt, sondern auch noch weitere. Unter anderem eben auch für Texturen.&lt;br /&gt;
&lt;br /&gt;
Die Texturmatrix funktioniert streng genommen genauso wie auch die Worldmatrix. Solange wir sie aktiv haben, wird sie von jedem Matrixbefehl berücksichtigt! Einziger wirklicher Unterschied ist, dass sie nicht die Position oder die Form eines Objektes beeinflusst, sondern nur das Rendern der Textur selbst. Hö? Was meint der Kerl bloß damit?! Nun... stellt Euch vor, Ihr habt ein Quad und wollt darauf eine Textur bewegen, so dass es aussieht, als würde sie sich von rechts nach links bewegen! Was wir jedoch nicht wollen ist, dass sich das Objekt bewegt, sondern nur, das was darauf zu sehen ist. Stellt Euch vor, Ihr schaut aus einem Fenster und seht einen wolkigen Himmel, der Wind bläst die Wolken von einer Himmelsrichtung zur anderen. Ihr könntet so z.B. das Fenster als Quad nehmen und dann die Textur darauf zeichnen und glaubt mir, die Illusion würde auffliegen, sobald sich das Fenster mit der Textur bewegen soll. Nein, stattdessen bewegen wir nur die Textur auf dem Quad und zwar ohne das UV-Mapping anzutasten. Wir beeinflussen einfach die Art, wie die Textur auf das Quad projiziert werden soll. Dafür dient die Texturmatrix.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns mal vor, dass wir unser Quad zeichnen und eine Variable X haben, die wir bei jedem Rendervorgang leicht erhöhen. Dies soll die Bewegung darstellen. Alles was wir nun tun müssen ist, die Texturmatrix entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glMatrixMode(GL_TEXTURE);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  glTranslatef(x,0,0);&lt;br /&gt;
glMatrixMode(GL_MODELVIEW);&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist bereits der ganze Spuk! Wir teilen OpenGL durch glMatrixMode mit, dass sich ab sofort alle Veränderungen der Matrix nur noch auf die Texturmatrix beziehen sollen. Danach setzen wir diese sofort auf ihren Standardwert zurück. Der Grund hierfür sollte Euch von der Worldmatrix noch in Erinnerung sein. Anschließend ändern wir die Position der Textur auf dem Quad. Würden wir X jedes Mal um 1 Einheit erhöhen, so würde diese Operation ohne Effekt bleiben, da wir die Textur immer um ihre ganze Größe nach links projizieren würden. Würden wir X z.B. bei jedem Vorgang um 0.01 erhöhen, so würde die Textur sich langsam von rechts nach links bewegen. Ich denke, Ihr könnt bereits erahnen, welche Parameter dafür verwendet werden, um eine Textur von unten nach oben zu bewegen ;).&lt;br /&gt;
&lt;br /&gt;
Wichtig ist auf jeden Fall, dass Ihr anschließend mit glMatrixMode wieder die Worldmatrix aktiviert, da sonst alle weiteren Matrixmanipulationen auf die Texturmatrix angewandt werden würden. Denkt nicht, dass die Texturmatrix damit deaktiviert wird! Ab sofort wird auf das Objekt sowohl die World- als auch die Texturmatrix angewendet. Seht Ihr? Das Ganze ist doch gar nicht ganz so schlimm. Es versteht sich auch von selbst, dass Ihr glRotate und glScale ebenfalls darauf anwenden könnt, natürlich auch nach den gleichen Regeln auf die Worldmatrix. Experimentiert am Besten auch etwas mit diesen Einstellungen herum!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wir tapezieren unsere Welt mal anders==&lt;br /&gt;
===Am Fließband===&lt;br /&gt;
Eigentlich sollte an dieser Stelle bereits Schluss sein. Ich wurde allerdings während des Schreibens des Tutorials nach einer Sache gefragt und möchte die Chance nutzen, diese Frage zu beantworten und gleichzeitig das angewandte Wissen der vorhergehenden Lektion etwas zu vertiefen. &lt;br /&gt;
&lt;br /&gt;
Wir haben folgende Problematik: Wir brauchen eine animierte Textur auf einem Objekt. Dies könnte z.B. eine bewegte Lavamasse sein oder irgendwas Glibbriges, was am Boden wabbelt. Oder eben in unserem Fall eine Folge von Zahlen, die wie ein Countdown aufgelistet werden. Sicherlich könnte nun jemand von Euch auf die Idee kommen, viele einzelne Texturen zu laden und diese in einem Array zu speichern. Dies mag auch durchaus sinnvoll sein nicht jedoch, wenn es sich um kleine Bilder handelt (bei uns z.B. 32x32 Pixel).&lt;br /&gt;
&lt;br /&gt;
Auch bei Bitmap-Fonts würde man nie auf die Idee kommen, für jeden Buchstaben eine einzelne Textur zu verwenden, sondern vielmehr eine Textur mit allen Buchstaben darauf erstellen, da dies u.a. den Ladevorgang erheblich beschleunigt! Klingt einleuchtend oder? Aber wie sollen wir dem Programm mitteilen, welcher Teil der Textur auf welche &amp;quot;Ecke&amp;quot; geklebt werden soll? Nun... auch hierbei heißt des Lösungs Rätsel [Anm. des Lektors: Er macht's schon wieder. Herrlich...] UV-Mapping!&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers.gif]]&lt;br /&gt;
&lt;br /&gt;
Dies ist unsere Textur! Sie hat eine Gesamtlänge von 256x32 Bildpunkten und wie man leicht sehen kann, soll sie aus 8 Teilstücken bestehen. Die V-Koordinate können wir in diesem Fall getrost vernachlässigen, weil sie in diesem Fall immer konstant sein wird, weil wir die ganze Höhe der Textur verwenden wollen. Sie wäre nur dann interessant, wenn wir z.B. noch eine zweite Reihe darunter setzen würden. Ich denke jedoch, dass jemand der das gleich folgende verstanden hat, sofort eine Lösung für diese &amp;quot;Problematik&amp;quot; finden wird ;).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers2.gif]]&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass wir uns bewusst werden, dass eine Textur beim UV-Mapping immer von 0 bis 1 reicht. Um nun die einzelnen Bilder aus einer Textur auf ein Objekt zu setzen, müssen wir nichts anderes machen, als zu errechnen, an welcher Stelle ein Bild anfängt und wo es aufhört. Nur zur Kontrolle, damit es auch jeder begreift: Würden wir nur die erste Hälfte der Textur auf ein Objekt kleben, so müsste unsere U-Koordinate von 0 bis 0.5 reichen. Die zweite Hälfte hingegen von 0.5 - 1.0. Soweit klingt es doch noch alles logisch oder?&lt;br /&gt;
&lt;br /&gt;
Genauso müssen wir auch vorgehen, wenn wir einzelne Bilder auf einem Quad abbilden wollen. In unserem Fall müsste die U-Koordinate von 0 bis 1/8 reichen. Das zweite Bildchen hingegen von 1/8 bis 2/8 etc. D.h. wir wissen, dass jedes unserer Bilder 1/8 &amp;quot;Einheiten&amp;quot; lang ist! Und somit haben wir ja bereits eine Lösung für unser Problem. Um das ganze dynamisch auszudrücken: Wir brauchen nur die Größe der Textur durch die Anzahl der Bilder zu teilen. Bevor jemand einen Denkfehler macht: Es ist hierbei ganz egal, wie groß die Textur wirklich ist (hier 256x32 Pixel). Dank OpenGL errechnen wir das UV-Mapping ja in absoluten Größen.&lt;br /&gt;
Nun der Code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;PicLength:= 1 / PicCount;&lt;br /&gt;
PicPos:=Round(Pic)*PicLength;&lt;br /&gt;
glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(PicPos,		    1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 0); glVertex3f(1,-1,0);&lt;br /&gt;
  glTexCoord2f(PicPos,		    0); glVertex3f(-1,-1,0);&lt;br /&gt;
glEnd;&lt;br /&gt;
&lt;br /&gt;
Pic:=Pic + MovementValue;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pic ist in diesem Fall eine Variable vom Typ Single, die langsam erhöht wird. Wir runden den Wert hier, so dass beim Erreichen eines jeden ganzzahligen Wertes das nächste Bild angezeigt wird. Wir multiplizieren die Nummer des anzuzeigenden Bildes mit der Breite eines Bildes, um die Anfangsposition zu erhalten und addieren dann noch eine volle Bildbreite dazu, um die Endposition zu erhalten. Hört sich gewaltig gefährlich an, liegt aber mehr an meinem mangelnden Ausdruck als an der Schwierigkeit dieses Problems ;).&lt;br /&gt;
&lt;br /&gt;
Im Sample werdet Ihr noch sehen, was passiert, wenn man den Wert nicht rundet. Man erhält in diesem Fall einen &amp;quot;flüssigen&amp;quot; Bildübergang. Letztendlich gibt es viele Möglichkeiten, solche Ideen zu implementieren. Nehmt dies einfach als kleineren Gedankenschub und vor allem: Werdet Euch bewusst, was genau dort passiert! Eine Menge toller Dinge lassen sich mit einem guten UV-Mapping erzielen.&lt;br /&gt;
Wer noch etwas umherexperimentieren will kann gern versuchen selbes Ziel mit Hilfe der Texturenmatrix zu erreichen. Die Lösung ist verblüffend einfach.&lt;br /&gt;
&lt;br /&gt;
===Terraforming mal anders===&lt;br /&gt;
Relativ lange habe ich nach einem guten Beispiel für folgende Problematik gesucht: Ich wollte Euch die UV-Koordinaten etwas näher bringen und Euch zeigen, wofür man sie einsetzen kann. Irgendwie wollte mir nichts Interessantes aus meinem Kopf entspringen bis ich irgendwann in einigen alten Programmen von mir rumgewühlt habe und einen alten Terrainrenderer von mir fand. Schon war die Idee da! Wir schreiben ein kleines Programm, das eine ganz simple, unoptimierte Landschaft rendern wird. Das hört sich sicherlich Anfangs relativ gewaltig an, mit etwas Verständnis für die oberen Probleme sollte dies jedoch kein Problem für Euch sein.&lt;br /&gt;
&lt;br /&gt;
Zuvor allerdings ein paar Gedankenspiele. Zunächst widmen wir uns kurz der Texturiering. Wie würde die simpelste Landschaft aussehen, die wir uns vorstellen können? Richtig! Sie wäre ein einfaches, flach liegendes Quadrat mit einer Textur überzogen, der Wand aus unserem ersten Versuch sehr ähnlich! Dies hat jedoch einen klitzekleinen Nachteil: Wir könnten keine Höhenstufen einbauen und ohne die wäre die Landschaft nur halb so realistisch. Denn wir wollen versuchen, folgende Szene zu zaubern:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscape.gif|thumb|256px|none|eine Lanschaft]]&lt;br /&gt;
Um allerdings Höhen einzubinden, müssen wir die Landschaft in viele kleinen Quads unterteilen, die natürlich an Ihren Eckpunkten unterschiedliche Höhen haben, sich jedoch jeweils einige Punkte teilen. Es versteht sich von selbst, dass diese die gleiche Höhe haben müssen, damit die Landschaft auch durchgängig ist und nicht irgendwelche mysteriösen Löcher darauf erscheinen ;).&lt;br /&gt;
Auf folgendem Screenshot kann man dies deutlich erkennen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landwire.gif|thumb|256px|left|Gitter Ansicht der Landschaft]]&lt;br /&gt;
Technisch gesehen ist das Ganze einfach zu realisieren, da wir nur begreifen müssen, dass alle Quads nebeneinander liegen und sich - bis auf die äußeren alle einen Eckpunkt teilen. Nun müssen wir beim Rendern jeden Eckpunkt nur noch vom angrenzenden Quad lesen und fertig ist die Landschaft. Ich will da nicht näher drauf eingehen, weil es sich hier nicht um ein Tutorial zur Landschaftsgestaltung handelt. Der Code sollte sich eigentlich von selbst erklären.&lt;br /&gt;
&lt;br /&gt;
Vielmehr sollten wir uns einer anderen Problematik widmen! Nämlich wie zur Hölle texturieren wir die Landschaft so, dass sie nicht zur Marke &amp;quot;augenfeindlich&amp;quot; gehört?&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscapeerror.gif|thumb|256px|right|wiederkehrende Landschaft]]&lt;br /&gt;
Wenn Euer erster Gedanke dabei &amp;quot;Boah, cool!&amp;quot; ist, dann gibt's eins auf die Finger! Das wollen wir doch nicht... wie sieht den die Landschaft aus. Eine immer wiederkehrende Landschaft -&amp;gt; man erkennt sofort, dass wir hierbei auf jedes Quad die gleiche Textur geklebt haben. Doch wie schaffen wir es nun, dass wir eine Textur über alle Quads ziehen, so dass die ganze Landschaft mit einer Textur überzogen ist anstatt nur über ein einzelnes Feld?&lt;br /&gt;
Nun, des Lösungs Geheimnis [Anm. des Lektors: Ich liebe ihn dafür! Andere lösen Rätsel. Er geheimnist Lösungen] sind eben unsere UV-Koordinaten und einige pfiffige Köpfe unter Euch sollten bereits einen ersten Verdacht haben. Denn die erste Idee sollte es sein, den linken unteren Punkt eine UV-Koordinate von (0/0) zu geben und der rechten oberen (1/1).&lt;br /&gt;
Alles was wir nun also machen müssen, ist, uns die entsprechenden UV-Koordinaten für die Quads dazwischen auszurechnen und sie dann den Punkten zuzuweisen. Dafür benötigen wir zunächst die Breite eines Quads. Mit normaler Logik lässt sich folgende Aussage aufstellen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;qw:=1 / XCount&lt;br /&gt;
qh:=1 / YCount;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Ein Quad benötigt die Länge von 1 durch die Anzahl der Quads in einer Reihe oder Spalte. Genauso verhält es sich auch mit der Höhe. Nun brauchen wir beim Rendern nur noch dem jeweiligen Quad in einer For-Schleife die entsprechende Koordinate zuzuweisen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;U:=1 / XCount;&lt;br /&gt;
V:=1 / YCount;&lt;br /&gt;
&lt;br /&gt;
for y:=0 to YCount-1 do&lt;br /&gt;
begin&lt;br /&gt;
  glPushMatrix;&lt;br /&gt;
  for x:=0 to XCount-1 do&lt;br /&gt;
  begin&lt;br /&gt;
    glBegin(GL_QUADS);&lt;br /&gt;
      glTexCoord2f(U*x,     V*(y+1)); &lt;br /&gt;
      glVertex3f(0,  Map[x,y+1],  0);&lt;br /&gt;
      glTexCoord2f(U*x,     V*y);     &lt;br /&gt;
      glVertex3f(0,  Map[x,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*y);     &lt;br /&gt;
      glVertex3f(1,  Map[x+1,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*(y+1));  &lt;br /&gt;
      glVertex3f(1, Map[x+1,y+1],  0);&lt;br /&gt;
    glEnd;&lt;br /&gt;
    glTranslatef(1,0,0);&lt;br /&gt;
  end;&lt;br /&gt;
  glPopMatrix;&lt;br /&gt;
  glTranslatef(0,0,-1);&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Das sieht nach einem herben Stück Arbeit aus oder? Aber wenn Ihr Euch das ganze mal aufzeichnet und im Kopf durchspielt, wird der Groschen fallen. Denkt mal etwas darüber nach! Wenn es dann doch noch Probleme mit dem Verständnis geben sollte, wird das nächste Kapitel hoffentlich jedes Missverständnis aus dem Wege räumen ;).&lt;br /&gt;
&lt;br /&gt;
==Nachwort==&lt;br /&gt;
Okay... ich hoffe Ihr fühlt Euch nach der Abarbeitung dieses Tutorials genauso wie ich, nachdem ich es für Euch geschrieben habe... nämlich elend. Irgendwie wurde das immer mehr und ich sagte mir immer wieder &amp;quot;nein, dass ist nicht genug. Das muss genauer und anschaulicher werden&amp;quot;. Dies ist auch der Grund dafür, warum dieses eines der größten Tutorials mit den meisten Bildern usw geworden ist. Erst sollte es noch etwas mehr werden und dann in mehrere Tutorials aufgespaltet werden, allerdings glaube ich mit diesem Tutorial einen guten Mittelweg zwischen Information und Totlabern gefunden zu haben. Lasst es mich wissen, wie Ihr dazu steht!&amp;lt;br&amp;gt;&lt;br /&gt;
Und bevor die Kritiker gleich wieder alle aus Ihren Löchern kommen und mir sagen, dass einige Bereich einfach als gegeben angenommen werden; denen sei nur gesagt, dass wir u.a. auch versuchen Rücksicht auf Leute zu nehmen, die noch nie 3D programmiert haben und vielleicht Eurem Wissen nicht standhalten können. Daher halte ich es hier für wichtiger, Grundlagen wie UV-Koordinaten und den Einsatz von Texturen zu erklären, als ihnen tausende von Zeilen um die Ohren zu hauen, wie sie die Bytes von der Festplatte in den Arbeitsspeicher laden können. Um jedoch keine Wissenslöcher offen zu lassen: Ihr könnt Euch sicher sein, dass spezielle Tutorials folgen werden, die sich speziell mit dem Laden verschiedener Formate beschäftigen und die genaue Interna (was im Hintergrund abläuft) zu erklären versuchen. Auch das Alpha Blending wird hier mehr zu &amp;quot;Show-Zwecken&amp;quot; verwendet und wird zusammen mit dem Z-Buffer genauer erklärt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Also bloß keine falsche Hektik! Ich weiß ... einige von Euch sind recht ungeduldig, aber ständiges Nachfragen und Drängeln führt zu nichts. Versucht Fragen lieber ins Forum zu setzen, damit dort ein wenig Leben reinkommt. Denn wenn es dort belebter wird, kommen auch schneller neue Leute und vielleicht sind ja auch welche dabei, die dann das DGL-Team entlasten können. Also nutzt bitte das Forum, anstatt andauernd per ICQ oder Mail irgendwelche Fragen zu stellen! Die Antwort wird auch nicht viel länger auf sich warten lassen. Im Forum jedoch ist alles dokumentiert und auch anderen zugänglich, so dass ich nicht die gleiche Frage bis zu 5 mal am Tag beantworten muss. Sorry aber das geht einem auf die Nerven und vor allem auf die Zeit ;). Schließlich sind wir keine Maschinen sondern Menschen, die auch ein privates Leben haben ^__-.&lt;br /&gt;
&lt;br /&gt;
Glaubt uns, wir investieren einen sehr großen Teil unserer Zeit in dieses Projekt und solch ein Tutorial lässt sich nicht binnen weniger Tage anfertigen. Jeder der so etwas bereits einmal gemacht hat, wird wissen was ich meine. Es muss ein Konzept her, es müssen Samples geschrieben, Screenshots gemacht werden und ein halbwegs verständlicher Text her. Und nichtsdestotrotz soll es am Ende auch noch passen, einem möglichst großen Publikum Wissen vermitteln, am Besten von Schreib- und Sprachfehlern befreit und in einem halbwegs ansehnlichen HTML-Dokument präsentiert werden. Ein langer Weg ;).&lt;br /&gt;
Okay, in diesem Sinne, bis bald ;)!&lt;br /&gt;
btw: Vielen Dank an Magellan für die Bereitstellung und Integration seiner &amp;quot;besonderen Lernleistung&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Euer&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_lektion3]]|[[Tutorial_lektion5]]}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Lektion4]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15375</id>
		<title>Tutorial Lektion 4</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15375"/>
				<updated>2005-12-13T20:30:46Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Tapeten besorgen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Texturen, Tapeten und Ihre Tücken=&lt;br /&gt;
&lt;br /&gt;
==Vorwort==&lt;br /&gt;
Hi Leute,&lt;br /&gt;
kaum zu glauben aber wahr. Dieses Tutorial wird ausnahmsweise mal etwas mehr Erholung sein. Zumindest am Anfang. Was wir bisher erreicht haben ist ja alles schön, nett, praktisch und auch wichtig als Grundlage aber wenn wir aus dem Fenster sehen hören wir die Vöglein zwitschern. Hö? Wir hören was sehend? Es ist tiefste Nacht? Es muss Frühling sein ^__^.&amp;lt;br&amp;gt;&lt;br /&gt;
Und was macht man da normalweise? Wir kramen herum und machen einen großen Frühjahrsputz... die Schränke abziehen und alles schön sauber und ordentlich machen. Hach... es dürstet mich richtig danach... :D (means... *würg*).&amp;lt;br&amp;gt;&lt;br /&gt;
Da unsere Tutorials bisher Gott sei Dank keine dreckige Sache waren werden wir das mit dem Saubermachen einfach mal wegfallen lassen und uns nur mit einem Tapetenwechsel begnügen. In der Tat werden wir ab jetzt unseren Tutorials mehr grafisches Gewicht zumuten. Endlich haben die blauen Dreiecke ein Ende! Ich wünsche Euch viel Spaß ;).&lt;br /&gt;
&lt;br /&gt;
==Crash-Kurs im Handwerk des Tapezierens==&lt;br /&gt;
&lt;br /&gt;
===Ich verstehe nur &amp;quot;Renovierung&amp;quot;?===&lt;br /&gt;
Ich finde es immer wieder erschreckend Leute im Internet zu treffen, die nicht wissen was eine Textur ist... ich meine, kennen keinen Kafka, keine Quantenphysik und wissen nicht einmal wo man die Systemsteuerung findet. Wie soll man solch einem Menschen erklären, was eine Textur ist?&lt;br /&gt;
Nun, am Besten fangen wir mit einem möglichst praktischen Beispiel an. Texturen sind wie... Tapeten. Wir blicken nun zu unserer linken Seite. Der Autor erwartet nun ein DirectMind-Uplink zum Empfangen der visuellen Bildsignale. Dort haben wir eine schöne Wand... quadratisch in ihrer Form. Wollen wir diese mit einer Tapete verzieren, gehen wir in den nächsten Baumarkt, suchen uns eine hübsche aus und bringen diese an der Wand an. Natürlich haben wir eine Große geholt, und fangen nicht mit kleinen Streifen an.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn dann alles geklappt hat stehen wir vor dieser Wand und begutachten die Tapete in voller Pracht direkt vor uns. Wir haben die Wand texturiert. Streng genommen machen wir auch bei OpenGL nichts anderes, als ein Bild zu laden und dieses auf eine Fläche zu kleben. Wir werden uns jedoch auf Dauer nicht damit begnügen immer nur quadratische Flächen zu texturieren, sondern durchaus auch mal Dreiecke oder andere Vielecke. Und auch hat man uns Werkzeuge in die Hand gegeben um diese Textur noch nachträglich an der Wand zu verschieben ohne dass wir sie abnehmen müssen. Ist doch super. Es lebe die virtuelle Welt!&lt;br /&gt;
&lt;br /&gt;
===Tapezieren leicht gemacht!===&lt;br /&gt;
Okay, wir haben lange genug um den heißen Brei herumgeredet und sollten uns nun endlich auf die Arbeit stürzen. Jeder von uns sollte in der Lage sein, ein Quadrat in OpenGL genau vor unserer Nase zu erzeugen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_nonetex.gif|thumb|256px|left|Leeres Quadrat]]&lt;br /&gt;
Spätestens nun sollte die gleiche Frage aufkommen, wie bei jedem, der zum ersten Mal versucht, eine Tapete an die Wand zu bringen: &amp;quot;Wie rum muss ich das Ding da befestigen?&amp;quot;. Immerhin müssen wir uns nicht um den Leim kümmern, das erledigt unsere Grafikkarte bzw. OpenGL für uns ;).&lt;br /&gt;
&lt;br /&gt;
Wer noch nie 3D programmiert hat wird im ersten Moment vielleicht fälschlicherweise denken, dass man die Position der Textur per Weltkoordinaten definiert. Das hätte allerdings fatale Folgen sobald sich das Objekt im Raum bewegt. Wir müssten die Position jedes mal neu berechnen. Um eben dieses Problem zu umgehen, geht man in der 3D-Programmierung einen anderen Weg. Man vergibt einfach für jede Ecke eines Objektes eine Koordinate der Textur. OpenGL errechnet dann aus diesen Texturkoordinaten das Stück der Textur, das dann über das gesamt Objekt projiziert wird.&lt;br /&gt;
&lt;br /&gt;
Die Rede ist hierbei vom so genannten UV-Mapping, welches vor allem bei Anfängern ein leichtes Gefühl des Unbehagens auslösen sollte. Es ist jedoch nur halb so wild, wenn man es halbwegs verstanden hat.&lt;br /&gt;
&lt;br /&gt;
Betrachten wir gleich mal folgendes Bild und versuchen, uns in die Problematik hineinzuversetzen. Da Texturen unterschiedliche Größen haben können wurden so genannte Texturkoordinaten eingeführt. Es ist total egal wie groß eine Textur ist, da sie nur einen Wertebereich von 0 bis 1 haben kann. Das heißt, wenn eine Textur 256x256 groß ist und eine andere 512x512, so haben beide eine maximale Größe von 1. Wir brauchen also das UV-Mapping nicht verändern, selbst wenn ein Objekt eine neue Textur mit anderer Größe erhält.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Auf diesem Bild sehen wir zum einen die Textur, die wir verwenden wollen, zum anderen das Objekt, auf das &amp;quot;geklebt&amp;quot; werden soll. Natürlich sieht das in der Realität nicht so aus. Ich denke aber diese Darstellung erleichtert das Verstehen ;).&lt;br /&gt;
&lt;br /&gt;
Die untere linke Ecke der Textur trägt die Texturkoordinaten von (0 / 0) (d.h. u = 0 und v = 0), die obere linke Ecke (0 / 1), die obere rechte Ecke (1 / 1) und schließlich die untere rechte Ecke die Koordinaten (1 / 0). Das heißt alles was wir machen müssen um auf unser Objekt eine Textur zu kleben ist dem jeweiligen Eckpunkt unseres Quadrates die entsprechende Texturkoordinate zuzuweisen. Wobei in diesem Sinne korrekt in Anführungszeichnen stehen sollte. Es gibt kein falsches UV-Mapping. Man kann tolle Sachen mit diesen Textur-Koordinaten machen und so z.B. auch eine Textur auf einem Objekt spiegeln. Dafür müssten wir in unserem Beispiel nur die linken und rechten UV-Mapping vertauschen und z.B. für den zweiten Punkt die Koordinaten von (1 / 1) setzen und dafür beim dritten (0/ 1). Genauso würden wir auch die unteren vertauschen. Die UV-Koordinaten, wie sie oben angegeben sind bewirken nur, dass die Textur, so wie sie in der Datei vorkommt auch auf das Objekt geklebt wird. Selbstverständlich ist es auch möglich eine Textur gekachelt aufzukleben indem Ihr Texturkoordinaten &amp;gt; 1 vergebt. Ebenso ist es möglich nur Teile einer Textur zu verwenden. Spielt ruhig ein wenig damit herum und schaut Euch an was passiert! Auf einige tolle Spielereien kommen wir zum Schluss noch mal zurück :).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv_02.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Sicherlich brennt es einigen von Euch nun bereits unter den Finger und Ihr fragt &amp;quot;Wie kann ich denn die UV-Koordinaten den Eckpunkten der Fläche zuweisen?&amp;quot;. Nun, zunächst funktioniert das ähnlich wie bei allen Dingen unter OpenGL. Wir setzen eine UV-Koordinate und solange wir nichts verändern werden alle Punkte mit diesen Koordinaten versehen bis wir andere Instruktionen geben. In unserem Fall müssen wir dies natürlich nach jedem Punkt machen. Die Funktion, die dafür verwendet wird heißt [[glTexCoord]]. Um also eine Textur auf unserem Quad zu projizieren, benötigen wir folgenden Code:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;!-- Zeilenumbrüche sind drinnen damit das Bild nicht die Code-Boc verunstaltet --&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(0,0); glVertex3f(-1,-1,0);&lt;br /&gt;
  glTexCoord2f(0,1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(1,1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(1,0); glVertex3f(1,-1,0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das klappt doch wunderbar oder? Damit wir die Textur aber auch wirklich genießen können müssen wir Texturing mit Hilfe von glEnable und dem Token GL_TEXTURE_2D aktivieren. Mit Hilfe von glDisable und demselben Token ist es dann auch möglich Objekte zu Zeichnen, die über keine Texturen verfügen. Andernfalls würde nämlich die zuletzt gesetzte Textur und die Texturkoordinaten des letzten glTexCoord-Aufrufs verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Doch eine Kleinigkeit habe ich Euch nun doch noch verschwiegen! Wir müssen natürlich noch die richtige Textur setzen damit OpenGL überhaupt weiß, was auf diesem Quad gezeichnet werden soll. Dies ist an sich noch relativ einfach, allerdings müssen wir diese auch noch in den Speicher bekommen, damit sie überhaupt zur Verfügung steht. Nun wird's theoretisch ;).&lt;br /&gt;
&lt;br /&gt;
===Tapeten besorgen===&lt;br /&gt;
Ich werde jetzt nicht näher darauf eingehen, wie man Texturen erstellt. Vielleicht gibt's ja einige Photoshopexperten unter Euch, die Lust haben einige Ihrer Tricks den anderen in Form eines Tutorials zu zeigen.&lt;br /&gt;
&lt;br /&gt;
Zunächst einmal müssen wir uns die eigentlichen Bilddaten besorgen. Wir werden das jetzt in diesem Tutorial mit [[SDL]] machen es gibt jedoch auch die Möglichkeit die Daten manuell zu laden das könnt Ihr hier nachlesen:&lt;br /&gt;
* [[TGA Bilder laden]]&lt;br /&gt;
Es gibt allerdings auch Texturloader die Euch die nächsten Kapitel abnehmen und das alles für Euch machen. glBitmap ist so ein Loader. Mehr dazu erfahrt Ihr in dem [[Glbitmap_loader|glBitmap]]-Artikel.&lt;br /&gt;
&lt;br /&gt;
Bei SDL rufen wir nur [[IMG_Load]] auf und prüfen dann ob das Laden erfolgreich war. Hierbei sei erwähnt, dass es unter Linux zu Problemen führen kann, wenn ein Programm nicht aus einer Konsole heraus gestartet wurde. In diesem Fall sind die Pfade zu den Texturen nämlich falsch gesetzt und das Laden würde fehlschlagen. Abhilfe schafft man durch das Verwenden von absoluten Pfaden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;uses SDL, SDL_Image;&lt;br /&gt;
&lt;br /&gt;
var &lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load(ExtractFileDir(paramStr(0))+'/wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das war es dann auch schon... Wir haben die Textur im Speicher. Doch was nun?&lt;br /&gt;
&lt;br /&gt;
===Texturen richtig zubereitet===&lt;br /&gt;
Nachdem sich unsere Textur nun im Speicher des Computers befindet, geht es darum, daraus auch eine richtige Textur zu machen, damit wir diese in OpenGL anzeigen können. Bisher befinden sich ja nur die Rohdaten im Speicher! Hierfür teilen wir OpenGL mit, dass wir eine neue Textur erzeugen wollen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glGenTextures(1, @TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TexID ist in diesem Fall ein gluInt, kann aber genauso gut ein Array davon sein, um mehrere Texturen zu erzeugen. Genau dafür wird dann auch der erste Parameter verwendet, der OpenGL mitteilt, wie viele Texturen in dieses Array geschrieben werden sollen. In unserem Fall ist dies eben nur ein Element. Aber was ist ist das für ein Wert in TexID? OpenGL verwaltet die Texturen anhand eindeutiger Namen. glGenTextures ermittelt einen oder mehrere bisher ungenutzte Namen und schreibt diese in TexID. Durch TexId können wir unsere Textur ab sofort also eindeutig identifizieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBindTexture(GL_TEXTURE_2D, TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir teilen OpenGL mit, dass sich von nun an alle Änderungen und Anweisungen, die sich auf Texturen beziehen auf die Textur TexID beziehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die folgenden beiden Zeilen sind zwar nicht wirklich nötig, um eine Textur zu erzeugen aber glaubt mir, sie werden ansonsten potthässlich aussehen. Wir werden in einem anderen Tutorial näher auf dessen Bedeutung eingehen, nämlich den so genannten Textur-Filtern. Die momentane Einstellung ist leicht rechenlastig, jedoch auch von recht guter Qualität. Ihr werdet anfangs keine Probleme mit der Geschwindigkeit bekommen ;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu guter letzt werden müssen wir die Bildinformationen in unserem TBitmap-Objekt irgendwie OpenGL mitteilen. Dies übernimmt die Funktion glTexImage2D:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Parameter steht für den Typ der Textur. Die Dimension des Typs muss hier mit der des Befehls übereinstimmen (glTexImage2D erlaubt also nur GL_TEXTURE_2D). Der zweite Parameter gibt die Nummer des Level of Detail (LoD) an. Für den Anfang reicht hier der Level 0. Der dritte Parameter gibt an, wie viele Farbkomponenten in dem Bild enthalten sind (1-4). Die zwei folgenden Parameter übermitteln OpenGL die Breite und die Höhe des Bildes. Der sechste Parameter gibt die Breite des Rahmens an. Im siebenten Parameter wird das Format verlangt, in welcher Reihenfolge die einzelnen Farbkomponenten gespeichert sind. Bei Bitmaps ist das immer die Reihenfolge Blau, Grün, Rot. Der Typ, der einzelnen Farbwerte muss im 8. Parameter angegeben werden. Letztendlich müssen im 9. Parameter nur noch die Bildpunkte selbst übergeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit Hilfe dieser Funktion sollten nur Texturen der Größe 2^n x 2^n erzeugt werden. Andernfalls werdet Ihr die Textur nicht in Ihrer vollen Schönheit, d.h. überhaupt nicht betrachten können. Es gibt jedoch Möglichkeiten Texturen zu laden, die nicht die Größe 2^n entsprechen. Die Funktion [[gluBuild2DMipmaps]] bildet hier beispielsweise eine Alternative.&amp;lt;br&amp;gt;&lt;br /&gt;
Das war es auch schon. Wer mehr über die einzelnen Parameter und Befehle wissen will ist herzlich eingeladen in unserem Wiki umherzustöbern und sein Wissen zu erweitern um später selbst vielleicht einmal ein paar Artikel im Wiki zu veröffentlichen.&lt;br /&gt;
&lt;br /&gt;
Die Daten im Arbeitsspeicher brauchen wir nun nicht mehr. Bei SDL geben wir sie so frei:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;SDL_FreeSurface(tex);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fassen wir das ganze bei SDL nochmal zusammen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;var&lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load('./wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin		&lt;br /&gt;
    glGenTextures(1, @texture);&lt;br /&gt;
    glBindTexture(GL_TEXTURE_2D, texture);&lt;br /&gt;
		&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
		&lt;br /&gt;
    // Achtung! Einige Bildformate erwarten statt GL_RGB, GL_BGR. Diese Konstante fehlt in den Standard-Headern&lt;br /&gt;
    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&lt;br /&gt;
&lt;br /&gt;
    SDL_FreeSurface(tex);&lt;br /&gt;
  end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kommt aber bitte nicht auf die Idee die Textur in euerer Hauptschleife wieder und wieder neu zu laden. Es reicht die Textur einmal zu laden und von da an steht sie einem solange zur Verfügung bis man gedenkt sie wieder aus dem Grafikkartenspeicher zu entfernen.&amp;lt;br&amp;gt;&lt;br /&gt;
Das übernimmt die Funktion [[glDeleteTextures]]. glDeleteTextures funktioniert ähnlich wie [[glGenTextures]], nur dass die Texturen entfernt werden. Der erste Parameter gibt die Anzahl der zu löschenden Texturen an, während der zweite Parameter den Namen der Textur bzw. ein Array der Namen mehrerer Texturen verlangt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das ist doch für den Anfang nicht schlecht. Ihr solltet nun in der Lage sein, zumindest einfache Objekte zu texturieren. Das ist eigentlich das gesamte Grundprinzip. Natürlich gestaltet es sich schwieriger, ein komplexeres Objekt mit UV-Koordinaten zu versehen, als ein Quad, aber an der Technik selbst ändert sich nur wenig. Wir werden nun einige Spielereien zeigen, die man mit Texturen machen kann, damit Ihr ein Gefühl dafür bekommt, wie man ein Problem elegant umschiffen kann!&lt;br /&gt;
&lt;br /&gt;
==Die Rückkehr der Matrizen==&lt;br /&gt;
===Texturen===&lt;br /&gt;
Tja... und da ich ein Sadist bin [Anm. des Lektors: Ooooh ja!] werden wir uns nun nochmals den Matrizen zuwenden! Dachtet Ihr etwa, Ihr seid die Dinger schon wieder los? Ich habe Euch im letzten Tutorial angedroht, dass es nicht nur eine Matrix für die &amp;quot;Welt&amp;quot; gibt, sondern auch noch weitere. Unter anderem eben auch für Texturen.&lt;br /&gt;
&lt;br /&gt;
Die Texturmatrix funktioniert streng genommen genauso wie auch die Worldmatrix. Solange wir sie aktiv haben, wird sie von jedem Matrixbefehl berücksichtigt! Einziger wirklicher Unterschied ist, dass sie nicht die Position oder die Form eines Objektes beeinflusst, sondern nur das Rendern der Textur selbst. Hö? Was meint der Kerl bloß damit?! Nun... stellt Euch vor, Ihr habt ein Quad und wollt darauf eine Textur bewegen, so dass es aussieht, als würde sie sich von rechts nach links bewegen! Was wir jedoch nicht wollen ist, dass sich das Objekt bewegt, sondern nur, das was darauf zu sehen ist. Stellt Euch vor, Ihr schaut aus einem Fenster und seht einen wolkigen Himmel, der Wind bläst die Wolken von einer Himmelsrichtung zur anderen. Ihr könntet so z.B. das Fenster als Quad nehmen und dann die Textur darauf zeichnen und glaubt mir, die Illusion würde auffliegen, sobald sich das Fenster mit der Textur bewegen soll. Nein, stattdessen bewegen wir nur die Textur auf dem Quad und zwar ohne das UV-Mapping anzutasten. Wir beeinflussen einfach die Art, wie die Textur auf das Quad projiziert werden soll. Dafür dient die Texturmatrix.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns mal vor, dass wir unser Quad zeichnen und eine Variable X haben, die wir bei jedem Rendervorgang leicht erhöhen. Dies soll die Bewegung darstellen. Alles was wir nun tun müssen ist, die Texturmatrix entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glMatrixMode(GL_TEXTURE);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  glTranslatef(x,0,0);&lt;br /&gt;
glMatrixMode(GL_MODELVIEW);&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist bereits der ganze Spuk! Wir teilen OpenGL durch glMatrixMode mit, dass sich ab sofort alle Veränderungen der Matrix nur noch auf die Texturmatrix beziehen sollen. Danach setzen wir diese sofort auf ihren Standardwert zurück. Der Grund hierfür sollte Euch von der Worldmatrix noch in Erinnerung sein. Anschließend ändern wir die Position der Textur auf dem Quad. Würden wir X jedes Mal um 1 Einheit erhöhen, so würde diese Operation ohne Effekt bleiben, da wir die Textur immer um ihre ganze Größe nach links projizieren würden. Würden wir X z.B. bei jedem Vorgang um 0.01 erhöhen, so würde die Textur sich langsam von rechts nach links bewegen. Ich denke, Ihr könnt bereits erahnen, welche Parameter dafür verwendet werden, um eine Textur von unten nach oben zu bewegen ;).&lt;br /&gt;
&lt;br /&gt;
Wichtig ist auf jeden Fall, dass Ihr anschließend mit glMatrixMode wieder die Worldmatrix aktiviert, da sonst alle weiteren Matrixmanipulationen auf die Texturmatrix angewandt werden würden. Denkt nicht, dass die Texturmatrix damit deaktiviert wird! Ab sofort wird auf das Objekt sowohl die World- als auch die Texturmatrix angewendet. Seht Ihr? Das Ganze ist doch gar nicht ganz so schlimm. Es versteht sich auch von selbst, dass Ihr glRotate und glScale ebenfalls darauf anwenden könnt, natürlich auch nach den gleichen Regeln auf die Worldmatrix. Experimentiert am Besten auch etwas mit diesen Einstellungen herum!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wir tapezieren unsere Welt mal anders==&lt;br /&gt;
===Am Fließband===&lt;br /&gt;
Eigentlich sollte an dieser Stelle bereits Schluss sein. Ich wurde allerdings während des Schreibens des Tutorials nach einer Sache gefragt und möchte die Chance nutzen, diese Frage zu beantworten und gleichzeitig das angewandte Wissen der vorhergehenden Lektion etwas zu vertiefen. &lt;br /&gt;
&lt;br /&gt;
Wir haben folgende Problematik: Wir brauchen eine animierte Textur auf einem Objekt. Dies könnte z.B. eine bewegte Lavamasse sein oder irgendwas Glibbriges, was am Boden wabbelt. Oder eben in unserem Fall eine Folge von Zahlen, die wie ein Countdown aufgelistet werden. Sicherlich könnte nun jemand von Euch auf die Idee kommen, viele einzelne Texturen zu laden und diese in einem Array zu speichern. Dies mag auch durchaus sinnvoll sein nicht jedoch, wenn es sich um kleine Bilder handelt (bei uns z.B. 32x32 Pixel).&lt;br /&gt;
&lt;br /&gt;
Auch bei Bitmap-Fonts würde man nie auf die Idee kommen, für jeden Buchstaben eine einzelne Textur zu verwenden, sondern vielmehr eine Textur mit allen Buchstaben darauf erstellen, da dies u.a. den Ladevorgang erheblich beschleunigt! Klingt einleuchtend oder? Aber wie sollen wir dem Programm mitteilen, welcher Teil der Textur auf welche &amp;quot;Ecke&amp;quot; geklebt werden soll? Nun... auch hierbei heißt des Lösungs Rätsel [Anm. des Lektors: Er macht's schon wieder. Herrlich...] UV-Mapping!&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers.gif]]&lt;br /&gt;
&lt;br /&gt;
Dies ist unsere Textur! Sie hat eine Gesamtlänge von 256x32 Bildpunkten und wie man leicht sehen kann, soll sie aus 8 Teilstücken bestehen. Die V-Koordinate können wir in diesem Fall getrost vernachlässigen, weil sie in diesem Fall immer konstant sein wird, weil wir die ganze Höhe der Textur verwenden wollen. Sie wäre nur dann interessant, wenn wir z.B. noch eine zweite Reihe darunter setzen würden. Ich denke jedoch, dass jemand der das gleich folgende verstanden hat, sofort eine Lösung für diese &amp;quot;Problematik&amp;quot; finden wird ;).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers2.gif]]&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass wir uns bewusst werden, dass eine Textur beim UV-Mapping immer von 0 bis 1 reicht. Um nun die einzelnen Bilder aus einer Textur auf ein Objekt zu setzen, müssen wir nichts anderes machen, als zu errechnen, an welcher Stelle ein Bild anfängt und wo es aufhört. Nur zur Kontrolle, damit es auch jeder begreift: Würden wir nur die erste Hälfte der Textur auf ein Objekt kleben, so müsste unsere U-Koordinate von 0 bis 0.5 reichen. Die zweite Hälfte hingegen von 0.5 - 1.0. Soweit klingt es doch noch alles logisch oder?&lt;br /&gt;
&lt;br /&gt;
Genauso müssen wir auch vorgehen, wenn wir einzelne Bilder auf einem Quad abbilden wollen. In unserem Fall müsste die U-Koordinate von 0 bis 1/8 reichen. Das zweite Bildchen hingegen von 1/8 bis 2/8 etc. D.h. wir wissen, dass jedes unserer Bilder 1/8 &amp;quot;Einheiten&amp;quot; lang ist! Und somit haben wir ja bereits eine Lösung für unser Problem. Um das ganze dynamisch auszudrücken: Wir brauchen nur die Größe der Textur durch die Anzahl der Bilder zu teilen. Bevor jemand einen Denkfehler macht: Es ist hierbei ganz egal, wie groß die Textur wirklich ist (hier 256x32 Pixel). Dank OpenGL errechnen wir das UV-Mapping ja in absoluten Größen.&lt;br /&gt;
Nun der Code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;PicLength:= 1 / PicCount;&lt;br /&gt;
PicPos:=Round(Pic)*PicLength;&lt;br /&gt;
glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(PicPos,		    1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 0); glVertex3f(1,-1,0);&lt;br /&gt;
  glTexCoord2f(PicPos,		    0); glVertex3f(-1,-1,0);&lt;br /&gt;
glEnd;&lt;br /&gt;
&lt;br /&gt;
Pic:=Pic + MovementValue;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pic ist in diesem Fall eine Variable vom Typ Single, die langsam erhöht wird. Wir runden den Wert hier, so dass beim Erreichen eines jeden ganzzahligen Wertes das nächste Bild angezeigt wird. Wir multiplizieren die Nummer des anzuzeigenden Bildes mit der Breite eines Bildes, um die Anfangsposition zu erhalten und addieren dann noch eine volle Bildbreite dazu, um die Endposition zu erhalten. Hört sich gewaltig gefährlich an, liegt aber mehr an meinem mangelnden Ausdruck als an der Schwierigkeit dieses Problems ;).&lt;br /&gt;
&lt;br /&gt;
Im Sample werdet Ihr noch sehen, was passiert, wenn man den Wert nicht rundet. Man erhält in diesem Fall einen &amp;quot;flüssigen&amp;quot; Bildübergang. Letztendlich gibt es viele Möglichkeiten, solche Ideen zu implementieren. Nehmt dies einfach als kleineren Gedankenschub und vor allem: Werdet Euch bewusst, was genau dort passiert! Eine Menge toller Dinge lassen sich mit einem guten UV-Mapping erzielen.&lt;br /&gt;
Wer noch etwas umherexperimentieren will kann gern versuchen selbes Ziel mit Hilfe der Texturenmatrix zu erreichen. Die Lösung ist verblüffend einfach.&lt;br /&gt;
&lt;br /&gt;
===Terraforming mal anders===&lt;br /&gt;
Relativ lange habe ich nach einem guten Beispiel für folgende Problematik gesucht: Ich wollte Euch die UV-Koordinaten etwas näher bringen und Euch zeigen, wofür man sie einsetzen kann. Irgendwie wollte mir nichts Interessantes aus meinem Kopf entspringen bis ich irgendwann in einigen alten Programmen von mir rumgewühlt habe und einen alten Terrainrenderer von mir fand. Schon war die Idee da! Wir schreiben ein kleines Programm, das eine ganz simple, unoptimierte Landschaft rendern wird. Das hört sich sicherlich Anfangs relativ gewaltig an, mit etwas Verständnis für die oberen Probleme sollte dies jedoch kein Problem für Euch sein.&lt;br /&gt;
&lt;br /&gt;
Zuvor allerdings ein paar Gedankenspiele. Zunächst widmen wir uns kurz der Texturiering. Wie würde die simpelste Landschaft aussehen, die wir uns vorstellen können? Richtig! Sie wäre ein einfaches, flach liegendes Quadrat mit einer Textur überzogen, der Wand aus unserem ersten Versuch sehr ähnlich! Dies hat jedoch einen klitzekleinen Nachteil: Wir könnten keine Höhenstufen einbauen und ohne die wäre die Landschaft nur halb so realistisch. Denn wir wollen versuchen, folgende Szene zu zaubern:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscape.gif|thumb|256px|none|eine Lanschaft]]&lt;br /&gt;
Um allerdings Höhen einzubinden, müssen wir die Landschaft in viele kleinen Quads unterteilen, die natürlich an Ihren Eckpunkten unterschiedliche Höhen haben, sich jedoch jeweils einige Punkte teilen. Es versteht sich von selbst, dass diese die gleiche Höhe haben müssen, damit die Landschaft auch durchgängig ist und nicht irgendwelche mysteriösen Löcher darauf erscheinen ;).&lt;br /&gt;
Auf folgendem Screenshot kann man dies deutlich erkennen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landwire.gif|thumb|256px|left|Gitter Ansicht der Landschaft]]&lt;br /&gt;
Technisch gesehen ist das Ganze einfach zu realisieren, da wir nur begreifen müssen, dass alle Quads nebeneinander liegen und sich - bis auf die äußeren alle einen Eckpunkt teilen. Nun müssen wir beim Rendern jeden Eckpunkt nur noch vom angrenzenden Quad lesen und fertig ist die Landschaft. Ich will da nicht näher drauf eingehen, weil es sich hier nicht um ein Tutorial zur Landschaftsgestaltung handelt. Der Code sollte sich eigentlich von selbst erklären.&lt;br /&gt;
&lt;br /&gt;
Vielmehr sollten wir uns einer anderen Problematik widmen! Nämlich wie zur Hölle texturieren wir die Landschaft so, dass sie nicht zur Marke &amp;quot;augenfeindlich&amp;quot; gehört?&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscapeerror.gif|thumb|256px|right|wiederkehrende Landschaft]]&lt;br /&gt;
Wenn Euer erster Gedanke dabei &amp;quot;Boah, cool!&amp;quot; ist, dann gibt's eins auf die Finger! Das wollen wir doch nicht... wie sieht den die Landschaft aus. Eine immer wiederkehrende Landschaft -&amp;gt; man erkennt sofort, dass wir hierbei auf jedes Quad die gleiche Textur geklebt haben. Doch wie schaffen wir es nun, dass wir eine Textur über alle Quads ziehen, so dass die ganze Landschaft mit einer Textur überzogen ist anstatt nur über ein einzelnes Feld?&lt;br /&gt;
Nun, des Lösungs Geheimnis [Anm. des Lektors: Ich liebe ihn dafür! Andere lösen Rätsel. Er geheimnist Lösungen] sind eben unsere UV-Koordinaten und einige pfiffige Köpfe unter Euch sollten bereits einen ersten Verdacht haben. Denn die erste Idee sollte es sein, den linken unteren Punkt eine UV-Koordinate von (0/0) zu geben und der rechten oberen (1/1).&lt;br /&gt;
Alles was wir nun also machen müssen, ist, uns die entsprechenden UV-Koordinaten für die Quads dazwischen auszurechnen und sie dann den Punkten zuzuweisen. Dafür benötigen wir zunächst die Breite eines Quads. Mit normaler Logik lässt sich folgende Aussage aufstellen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;qw:=1 / XCount&lt;br /&gt;
qh:=1 / YCount;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Ein Quad benötigt die Länge von 1 durch die Anzahl der Quads in einer Reihe oder Spalte. Genauso verhält es sich auch mit der Höhe. Nun brauchen wir beim Rendern nur noch dem jeweiligen Quad in einer For-Schleife die entsprechende Koordinate zuzuweisen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;U:=1 / XCount;&lt;br /&gt;
V:=1 / YCount;&lt;br /&gt;
&lt;br /&gt;
for y:=0 to YCount-1 do&lt;br /&gt;
begin&lt;br /&gt;
  glPushMatrix;&lt;br /&gt;
  for x:=0 to XCount-1 do&lt;br /&gt;
  begin&lt;br /&gt;
    glBegin(GL_QUADS);&lt;br /&gt;
      glTexCoord2f(U*x,     V*(y+1)); &lt;br /&gt;
      glVertex3f(0,  Map[x,y+1],  0);&lt;br /&gt;
      glTexCoord2f(U*x,     V*y);     &lt;br /&gt;
      glVertex3f(0,  Map[x,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*y);     &lt;br /&gt;
      glVertex3f(1,  Map[x+1,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*(y+1));  &lt;br /&gt;
      glVertex3f(1, Map[x+1,y+1],  0);&lt;br /&gt;
    glEnd;&lt;br /&gt;
    glTranslatef(1,0,0);&lt;br /&gt;
  end;&lt;br /&gt;
  glPopMatrix;&lt;br /&gt;
  glTranslatef(0,0,-1);&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Das sieht nach einem herben Stück Arbeit aus oder? Aber wenn Ihr Euch das ganze mal aufzeichnet und im Kopf durchspielt, wird der Groschen fallen. Denkt mal etwas darüber nach! Wenn es dann doch noch Probleme mit dem Verständnis geben sollte, wird das nächste Kapitel hoffentlich jedes Missverständnis aus dem Wege räumen ;).&lt;br /&gt;
&lt;br /&gt;
==Nachwort==&lt;br /&gt;
Okay... ich hoffe Ihr fühlt Euch nach der Abarbeitung dieses Tutorials genauso wie ich, nachdem ich es für Euch geschrieben habe... nämlich elend. Irgendwie wurde das immer mehr und ich sagte mir immer wieder &amp;quot;nein, dass ist nicht genug. Das muss genauer und anschaulicher werden&amp;quot;. Dies ist auch der Grund dafür, warum dieses eines der größten Tutorials mit den meisten Bildern usw geworden ist. Erst sollte es noch etwas mehr werden und dann in mehrere Tutorials aufgespaltet werden, allerdings glaube ich mit diesem Tutorial einen guten Mittelweg zwischen Information und Totlabern gefunden zu haben. Lasst es mich wissen, wie Ihr dazu steht!&amp;lt;br&amp;gt;&lt;br /&gt;
Und bevor die Kritiker gleich wieder alle aus Ihren Löchern kommen und mir sagen, dass einige Bereich einfach als gegeben angenommen werden; denen sei nur gesagt, dass wir u.a. auch versuchen Rücksicht auf Leute zu nehmen, die noch nie 3D programmiert haben und vielleicht Eurem Wissen nicht standhalten können. Daher halte ich es hier für wichtiger, Grundlagen wie UV-Koordinaten und den Einsatz von Texturen zu erklären, als ihnen tausende von Zeilen um die Ohren zu hauen, wie sie die Bytes von der Festplatte in den Arbeitsspeicher laden können. Um jedoch keine Wissenslöcher offen zu lassen: Ihr könnt Euch sicher sein, dass spezielle Tutorials folgen werden, die sich speziell mit dem Laden verschiedener Formate beschäftigen und die genaue Interna (was im Hintergrund abläuft) zu erklären versuchen. Auch das Alpha Blending wird hier mehr zu &amp;quot;Show-Zwecken&amp;quot; verwendet und wird zusammen mit dem Z-Buffer genauer erklärt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Also bloß keine falsche Hektik! Ich weiß ... einige von Euch sind recht ungeduldig, aber ständiges Nachfragen und Drängeln führt zu nichts. Versucht Fragen lieber ins Forum zu setzen, damit dort ein wenig Leben reinkommt. Denn wenn es dort belebter wird, kommen auch schneller neue Leute und vielleicht sind ja auch welche dabei, die dann das DGL-Team entlasten können. Also nutzt bitte das Forum, anstatt andauernd per ICQ oder Mail irgendwelche Fragen zu stellen! Die Antwort wird auch nicht viel länger auf sich warten lassen. Im Forum jedoch ist alles dokumentiert und auch anderen zugänglich, so dass ich nicht die gleiche Frage bis zu 5 mal am Tag beantworten muss. Sorry aber das geht einem auf die Nerven und vor allem auf die Zeit ;). Schließlich sind wir keine Maschinen sondern Menschen, die auch ein privates Leben haben ^__-.&lt;br /&gt;
&lt;br /&gt;
Glaubt uns, wir investieren einen sehr großen Teil unserer Zeit in dieses Projekt und solch ein Tutorial lässt sich nicht binnen weniger Tage anfertigen. Jeder der so etwas bereits einmal gemacht hat, wird wissen was ich meine. Es muss ein Konzept her, es müssen Samples geschrieben, Screenshots gemacht werden und ein halbwegs verständlicher Text her. Und nichtsdestotrotz soll es am Ende auch noch passen, einem möglichst großen Publikum Wissen vermitteln, am Besten von Schreib- und Sprachfehlern befreit und in einem halbwegs ansehnlichen HTML-Dokument präsentiert werden. Ein langer Weg ;).&lt;br /&gt;
Okay, in diesem Sinne, bis bald ;)!&lt;br /&gt;
btw: Vielen Dank an Magellan für die Bereitstellung und Integration seiner &amp;quot;besonderen Lernleistung&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Euer&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_lektion3]]|[[Tutorial_lektion5]]}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Lektion4]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15374</id>
		<title>Tutorial Lektion 4</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15374"/>
				<updated>2005-12-13T20:27:29Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Tapezieren leicht gemacht! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Texturen, Tapeten und Ihre Tücken=&lt;br /&gt;
&lt;br /&gt;
==Vorwort==&lt;br /&gt;
Hi Leute,&lt;br /&gt;
kaum zu glauben aber wahr. Dieses Tutorial wird ausnahmsweise mal etwas mehr Erholung sein. Zumindest am Anfang. Was wir bisher erreicht haben ist ja alles schön, nett, praktisch und auch wichtig als Grundlage aber wenn wir aus dem Fenster sehen hören wir die Vöglein zwitschern. Hö? Wir hören was sehend? Es ist tiefste Nacht? Es muss Frühling sein ^__^.&amp;lt;br&amp;gt;&lt;br /&gt;
Und was macht man da normalweise? Wir kramen herum und machen einen großen Frühjahrsputz... die Schränke abziehen und alles schön sauber und ordentlich machen. Hach... es dürstet mich richtig danach... :D (means... *würg*).&amp;lt;br&amp;gt;&lt;br /&gt;
Da unsere Tutorials bisher Gott sei Dank keine dreckige Sache waren werden wir das mit dem Saubermachen einfach mal wegfallen lassen und uns nur mit einem Tapetenwechsel begnügen. In der Tat werden wir ab jetzt unseren Tutorials mehr grafisches Gewicht zumuten. Endlich haben die blauen Dreiecke ein Ende! Ich wünsche Euch viel Spaß ;).&lt;br /&gt;
&lt;br /&gt;
==Crash-Kurs im Handwerk des Tapezierens==&lt;br /&gt;
&lt;br /&gt;
===Ich verstehe nur &amp;quot;Renovierung&amp;quot;?===&lt;br /&gt;
Ich finde es immer wieder erschreckend Leute im Internet zu treffen, die nicht wissen was eine Textur ist... ich meine, kennen keinen Kafka, keine Quantenphysik und wissen nicht einmal wo man die Systemsteuerung findet. Wie soll man solch einem Menschen erklären, was eine Textur ist?&lt;br /&gt;
Nun, am Besten fangen wir mit einem möglichst praktischen Beispiel an. Texturen sind wie... Tapeten. Wir blicken nun zu unserer linken Seite. Der Autor erwartet nun ein DirectMind-Uplink zum Empfangen der visuellen Bildsignale. Dort haben wir eine schöne Wand... quadratisch in ihrer Form. Wollen wir diese mit einer Tapete verzieren, gehen wir in den nächsten Baumarkt, suchen uns eine hübsche aus und bringen diese an der Wand an. Natürlich haben wir eine Große geholt, und fangen nicht mit kleinen Streifen an.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn dann alles geklappt hat stehen wir vor dieser Wand und begutachten die Tapete in voller Pracht direkt vor uns. Wir haben die Wand texturiert. Streng genommen machen wir auch bei OpenGL nichts anderes, als ein Bild zu laden und dieses auf eine Fläche zu kleben. Wir werden uns jedoch auf Dauer nicht damit begnügen immer nur quadratische Flächen zu texturieren, sondern durchaus auch mal Dreiecke oder andere Vielecke. Und auch hat man uns Werkzeuge in die Hand gegeben um diese Textur noch nachträglich an der Wand zu verschieben ohne dass wir sie abnehmen müssen. Ist doch super. Es lebe die virtuelle Welt!&lt;br /&gt;
&lt;br /&gt;
===Tapezieren leicht gemacht!===&lt;br /&gt;
Okay, wir haben lange genug um den heißen Brei herumgeredet und sollten uns nun endlich auf die Arbeit stürzen. Jeder von uns sollte in der Lage sein, ein Quadrat in OpenGL genau vor unserer Nase zu erzeugen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_nonetex.gif|thumb|256px|left|Leeres Quadrat]]&lt;br /&gt;
Spätestens nun sollte die gleiche Frage aufkommen, wie bei jedem, der zum ersten Mal versucht, eine Tapete an die Wand zu bringen: &amp;quot;Wie rum muss ich das Ding da befestigen?&amp;quot;. Immerhin müssen wir uns nicht um den Leim kümmern, das erledigt unsere Grafikkarte bzw. OpenGL für uns ;).&lt;br /&gt;
&lt;br /&gt;
Wer noch nie 3D programmiert hat wird im ersten Moment vielleicht fälschlicherweise denken, dass man die Position der Textur per Weltkoordinaten definiert. Das hätte allerdings fatale Folgen sobald sich das Objekt im Raum bewegt. Wir müssten die Position jedes mal neu berechnen. Um eben dieses Problem zu umgehen, geht man in der 3D-Programmierung einen anderen Weg. Man vergibt einfach für jede Ecke eines Objektes eine Koordinate der Textur. OpenGL errechnet dann aus diesen Texturkoordinaten das Stück der Textur, das dann über das gesamt Objekt projiziert wird.&lt;br /&gt;
&lt;br /&gt;
Die Rede ist hierbei vom so genannten UV-Mapping, welches vor allem bei Anfängern ein leichtes Gefühl des Unbehagens auslösen sollte. Es ist jedoch nur halb so wild, wenn man es halbwegs verstanden hat.&lt;br /&gt;
&lt;br /&gt;
Betrachten wir gleich mal folgendes Bild und versuchen, uns in die Problematik hineinzuversetzen. Da Texturen unterschiedliche Größen haben können wurden so genannte Texturkoordinaten eingeführt. Es ist total egal wie groß eine Textur ist, da sie nur einen Wertebereich von 0 bis 1 haben kann. Das heißt, wenn eine Textur 256x256 groß ist und eine andere 512x512, so haben beide eine maximale Größe von 1. Wir brauchen also das UV-Mapping nicht verändern, selbst wenn ein Objekt eine neue Textur mit anderer Größe erhält.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Auf diesem Bild sehen wir zum einen die Textur, die wir verwenden wollen, zum anderen das Objekt, auf das &amp;quot;geklebt&amp;quot; werden soll. Natürlich sieht das in der Realität nicht so aus. Ich denke aber diese Darstellung erleichtert das Verstehen ;).&lt;br /&gt;
&lt;br /&gt;
Die untere linke Ecke der Textur trägt die Texturkoordinaten von (0 / 0) (d.h. u = 0 und v = 0), die obere linke Ecke (0 / 1), die obere rechte Ecke (1 / 1) und schließlich die untere rechte Ecke die Koordinaten (1 / 0). Das heißt alles was wir machen müssen um auf unser Objekt eine Textur zu kleben ist dem jeweiligen Eckpunkt unseres Quadrates die entsprechende Texturkoordinate zuzuweisen. Wobei in diesem Sinne korrekt in Anführungszeichnen stehen sollte. Es gibt kein falsches UV-Mapping. Man kann tolle Sachen mit diesen Textur-Koordinaten machen und so z.B. auch eine Textur auf einem Objekt spiegeln. Dafür müssten wir in unserem Beispiel nur die linken und rechten UV-Mapping vertauschen und z.B. für den zweiten Punkt die Koordinaten von (1 / 1) setzen und dafür beim dritten (0/ 1). Genauso würden wir auch die unteren vertauschen. Die UV-Koordinaten, wie sie oben angegeben sind bewirken nur, dass die Textur, so wie sie in der Datei vorkommt auch auf das Objekt geklebt wird. Selbstverständlich ist es auch möglich eine Textur gekachelt aufzukleben indem Ihr Texturkoordinaten &amp;gt; 1 vergebt. Ebenso ist es möglich nur Teile einer Textur zu verwenden. Spielt ruhig ein wenig damit herum und schaut Euch an was passiert! Auf einige tolle Spielereien kommen wir zum Schluss noch mal zurück :).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv_02.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Sicherlich brennt es einigen von Euch nun bereits unter den Finger und Ihr fragt &amp;quot;Wie kann ich denn die UV-Koordinaten den Eckpunkten der Fläche zuweisen?&amp;quot;. Nun, zunächst funktioniert das ähnlich wie bei allen Dingen unter OpenGL. Wir setzen eine UV-Koordinate und solange wir nichts verändern werden alle Punkte mit diesen Koordinaten versehen bis wir andere Instruktionen geben. In unserem Fall müssen wir dies natürlich nach jedem Punkt machen. Die Funktion, die dafür verwendet wird heißt [[glTexCoord]]. Um also eine Textur auf unserem Quad zu projizieren, benötigen wir folgenden Code:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;!-- Zeilenumbrüche sind drinnen damit das Bild nicht die Code-Boc verunstaltet --&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(0,0); glVertex3f(-1,-1,0);&lt;br /&gt;
  glTexCoord2f(0,1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(1,1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(1,0); glVertex3f(1,-1,0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das klappt doch wunderbar oder? Damit wir die Textur aber auch wirklich genießen können müssen wir Texturing mit Hilfe von glEnable und dem Token GL_TEXTURE_2D aktivieren. Mit Hilfe von glDisable und demselben Token ist es dann auch möglich Objekte zu Zeichnen, die über keine Texturen verfügen. Andernfalls würde nämlich die zuletzt gesetzte Textur und die Texturkoordinaten des letzten glTexCoord-Aufrufs verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Doch eine Kleinigkeit habe ich Euch nun doch noch verschwiegen! Wir müssen natürlich noch die richtige Textur setzen damit OpenGL überhaupt weiß, was auf diesem Quad gezeichnet werden soll. Dies ist an sich noch relativ einfach, allerdings müssen wir diese auch noch in den Speicher bekommen, damit sie überhaupt zur Verfügung steht. Nun wird's theoretisch ;).&lt;br /&gt;
&lt;br /&gt;
===Tapeten besorgen===&lt;br /&gt;
Ich werde jetzt nicht näher darauf eingehen, wie man Texturen erstellt, vielleicht gibt's ja einige Photoshop-Experten unter Euch, die Lust haben, einige Ihrer Tricks den anderen in Form eines Tutorials zu zeigen?&lt;br /&gt;
&lt;br /&gt;
Zunächst einmal müssen wir die uns die eigentlichen Bilddaten besorgen. Wir werden das jetzt in diesem Tutorial mit [[SDL]] machen es gibt jedoch auch die möglichkeit die Daten manuell zu laden das könnt ihr hier nachlesen:&lt;br /&gt;
* [[TGA Bilder laden]]&lt;br /&gt;
Es gibt allerdings auch Textur loader die euch die nächsten Kapitel abnehmen und das alles für euch machen. glBitmap ist so ein Loader, mehr dazu erfahrt ihr in dem [[Glbitmap_loader|glBitmap]]-Artikel.&lt;br /&gt;
&lt;br /&gt;
Bei SDL rufen wir nur [[IMG_Load]] auf und prüfen dann ob das Laden erfolgreich war. Hierbei sei erwähnt, dass es unter Linux zu Problemen führen kann, wenn ein Programm nicht aus einer Konsole heraus gestartet wurde. In diesem Fall sind die Pfade zu den Texturen nämlich falsch gesetzt und das Laden würde fehlschlagen. Abhilfe schafft man durch das Verwenden von absoluten Pfaden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;uses SDL, SDL_Image;&lt;br /&gt;
&lt;br /&gt;
var &lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load(ExtractFileDir(paramStr(0))+'/wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das war es dann auch schon... wir haben die Textur im Speicher Doch was nun?&lt;br /&gt;
&lt;br /&gt;
===Texturen richtig zubereitet===&lt;br /&gt;
Nachdem sich unsere Textur nun im Speicher des Computers befindet, geht es darum, daraus auch eine richtige Textur zu machen, damit wir diese in OpenGL anzeigen können. Bisher befinden sich ja nur die Rohdaten im Speicher! Hierfür teilen wir OpenGL mit, dass wir eine neue Textur erzeugen wollen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glGenTextures(1, @TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TexID ist in diesem Fall ein gluInt, kann aber genauso gut ein Array davon sein, um mehrere Texturen zu erzeugen. Genau dafür wird dann auch der erste Parameter verwendet, der OpenGL mitteilt, wie viele Texturen in dieses Array geschrieben werden sollen. In unserem Fall ist dies eben nur ein Element. Aber was ist ist das für ein Wert in TexID? OpenGL verwaltet die Texturen anhand eindeutiger Namen. glGenTextures ermittelt einen oder mehrere bisher ungenutzte Namen und schreibt diese in TexID. Durch TexId können wir unsere Textur ab sofort also eindeutig identifizieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBindTexture(GL_TEXTURE_2D, TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir teilen OpenGL mit, dass sich von nun an alle Änderungen und Anweisungen, die sich auf Texturen beziehen auf die Textur TexID beziehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die folgenden beiden Zeilen sind zwar nicht wirklich nötig, um eine Textur zu erzeugen aber glaubt mir, sie werden ansonsten potthässlich aussehen. Wir werden in einem anderen Tutorial näher auf dessen Bedeutung eingehen, nämlich den so genannten Textur-Filtern. Die momentane Einstellung ist leicht rechenlastig, jedoch auch von recht guter Qualität. Ihr werdet anfangs keine Probleme mit der Geschwindigkeit bekommen ;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu guter letzt werden müssen wir die Bildinformationen in unserem TBitmap-Objekt irgendwie OpenGL mitteilen. Dies übernimmt die Funktion glTexImage2D:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Parameter steht für den Typ der Textur. Die Dimension des Typs muss hier mit der des Befehls übereinstimmen (glTexImage2D erlaubt also nur GL_TEXTURE_2D). Der zweite Parameter gibt die Nummer des Level of Detail (LoD) an. Für den Anfang reicht hier der Level 0. Der dritte Parameter gibt an, wie viele Farbkomponenten in dem Bild enthalten sind (1-4). Die zwei folgenden Parameter übermitteln OpenGL die Breite und die Höhe des Bildes. Der sechste Parameter gibt die Breite des Rahmens an. Im siebenten Parameter wird das Format verlangt, in welcher Reihenfolge die einzelnen Farbkomponenten gespeichert sind. Bei Bitmaps ist das immer die Reihenfolge Blau, Grün, Rot. Der Typ, der einzelnen Farbwerte muss im 8. Parameter angegeben werden. Letztendlich müssen im 9. Parameter nur noch die Bildpunkte selbst übergeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit Hilfe dieser Funktion sollten nur Texturen der Größe 2^n x 2^n erzeugt werden. Andernfalls werdet Ihr die Textur nicht in Ihrer vollen Schönheit, d.h. überhaupt nicht betrachten können. Es gibt jedoch Möglichkeiten Texturen zu laden, die nicht die Größe 2^n entsprechen. Die Funktion [[gluBuild2DMipmaps]] bildet hier beispielsweise eine Alternative.&amp;lt;br&amp;gt;&lt;br /&gt;
Das war es auch schon. Wer mehr über die einzelnen Parameter und Befehle wissen will ist herzlich eingeladen in unserem Wiki umherzustöbern und sein Wissen zu erweitern um später selbst vielleicht einmal ein paar Artikel im Wiki zu veröffentlichen.&lt;br /&gt;
&lt;br /&gt;
Die Daten im Arbeitsspeicher brauchen wir nun nicht mehr. Bei SDL geben wir sie so frei:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;SDL_FreeSurface(tex);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fassen wir das ganze bei SDL nochmal zusammen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;var&lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load('./wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin		&lt;br /&gt;
    glGenTextures(1, @texture);&lt;br /&gt;
    glBindTexture(GL_TEXTURE_2D, texture);&lt;br /&gt;
		&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
		&lt;br /&gt;
    // Achtung! Einige Bildformate erwarten statt GL_RGB, GL_BGR. Diese Konstante fehlt in den Standard-Headern&lt;br /&gt;
    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&lt;br /&gt;
&lt;br /&gt;
    SDL_FreeSurface(tex);&lt;br /&gt;
  end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kommt aber bitte nicht auf die Idee die Textur in euerer Hauptschleife wieder und wieder neu zu laden. Es reicht die Textur einmal zu laden und von da an steht sie einem solange zur Verfügung bis man gedenkt sie wieder aus dem Grafikkartenspeicher zu entfernen.&amp;lt;br&amp;gt;&lt;br /&gt;
Das übernimmt die Funktion [[glDeleteTextures]]. glDeleteTextures funktioniert ähnlich wie [[glGenTextures]], nur dass die Texturen entfernt werden. Der erste Parameter gibt die Anzahl der zu löschenden Texturen an, während der zweite Parameter den Namen der Textur bzw. ein Array der Namen mehrerer Texturen verlangt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das ist doch für den Anfang nicht schlecht. Ihr solltet nun in der Lage sein, zumindest einfache Objekte zu texturieren. Das ist eigentlich das gesamte Grundprinzip. Natürlich gestaltet es sich schwieriger, ein komplexeres Objekt mit UV-Koordinaten zu versehen, als ein Quad, aber an der Technik selbst ändert sich nur wenig. Wir werden nun einige Spielereien zeigen, die man mit Texturen machen kann, damit Ihr ein Gefühl dafür bekommt, wie man ein Problem elegant umschiffen kann!&lt;br /&gt;
&lt;br /&gt;
==Die Rückkehr der Matrizen==&lt;br /&gt;
===Texturen===&lt;br /&gt;
Tja... und da ich ein Sadist bin [Anm. des Lektors: Ooooh ja!] werden wir uns nun nochmals den Matrizen zuwenden! Dachtet Ihr etwa, Ihr seid die Dinger schon wieder los? Ich habe Euch im letzten Tutorial angedroht, dass es nicht nur eine Matrix für die &amp;quot;Welt&amp;quot; gibt, sondern auch noch weitere. Unter anderem eben auch für Texturen.&lt;br /&gt;
&lt;br /&gt;
Die Texturmatrix funktioniert streng genommen genauso wie auch die Worldmatrix. Solange wir sie aktiv haben, wird sie von jedem Matrixbefehl berücksichtigt! Einziger wirklicher Unterschied ist, dass sie nicht die Position oder die Form eines Objektes beeinflusst, sondern nur das Rendern der Textur selbst. Hö? Was meint der Kerl bloß damit?! Nun... stellt Euch vor, Ihr habt ein Quad und wollt darauf eine Textur bewegen, so dass es aussieht, als würde sie sich von rechts nach links bewegen! Was wir jedoch nicht wollen ist, dass sich das Objekt bewegt, sondern nur, das was darauf zu sehen ist. Stellt Euch vor, Ihr schaut aus einem Fenster und seht einen wolkigen Himmel, der Wind bläst die Wolken von einer Himmelsrichtung zur anderen. Ihr könntet so z.B. das Fenster als Quad nehmen und dann die Textur darauf zeichnen und glaubt mir, die Illusion würde auffliegen, sobald sich das Fenster mit der Textur bewegen soll. Nein, stattdessen bewegen wir nur die Textur auf dem Quad und zwar ohne das UV-Mapping anzutasten. Wir beeinflussen einfach die Art, wie die Textur auf das Quad projiziert werden soll. Dafür dient die Texturmatrix.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns mal vor, dass wir unser Quad zeichnen und eine Variable X haben, die wir bei jedem Rendervorgang leicht erhöhen. Dies soll die Bewegung darstellen. Alles was wir nun tun müssen ist, die Texturmatrix entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glMatrixMode(GL_TEXTURE);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  glTranslatef(x,0,0);&lt;br /&gt;
glMatrixMode(GL_MODELVIEW);&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist bereits der ganze Spuk! Wir teilen OpenGL durch glMatrixMode mit, dass sich ab sofort alle Veränderungen der Matrix nur noch auf die Texturmatrix beziehen sollen. Danach setzen wir diese sofort auf ihren Standardwert zurück. Der Grund hierfür sollte Euch von der Worldmatrix noch in Erinnerung sein. Anschließend ändern wir die Position der Textur auf dem Quad. Würden wir X jedes Mal um 1 Einheit erhöhen, so würde diese Operation ohne Effekt bleiben, da wir die Textur immer um ihre ganze Größe nach links projizieren würden. Würden wir X z.B. bei jedem Vorgang um 0.01 erhöhen, so würde die Textur sich langsam von rechts nach links bewegen. Ich denke, Ihr könnt bereits erahnen, welche Parameter dafür verwendet werden, um eine Textur von unten nach oben zu bewegen ;).&lt;br /&gt;
&lt;br /&gt;
Wichtig ist auf jeden Fall, dass Ihr anschließend mit glMatrixMode wieder die Worldmatrix aktiviert, da sonst alle weiteren Matrixmanipulationen auf die Texturmatrix angewandt werden würden. Denkt nicht, dass die Texturmatrix damit deaktiviert wird! Ab sofort wird auf das Objekt sowohl die World- als auch die Texturmatrix angewendet. Seht Ihr? Das Ganze ist doch gar nicht ganz so schlimm. Es versteht sich auch von selbst, dass Ihr glRotate und glScale ebenfalls darauf anwenden könnt, natürlich auch nach den gleichen Regeln auf die Worldmatrix. Experimentiert am Besten auch etwas mit diesen Einstellungen herum!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wir tapezieren unsere Welt mal anders==&lt;br /&gt;
===Am Fließband===&lt;br /&gt;
Eigentlich sollte an dieser Stelle bereits Schluss sein. Ich wurde allerdings während des Schreibens des Tutorials nach einer Sache gefragt und möchte die Chance nutzen, diese Frage zu beantworten und gleichzeitig das angewandte Wissen der vorhergehenden Lektion etwas zu vertiefen. &lt;br /&gt;
&lt;br /&gt;
Wir haben folgende Problematik: Wir brauchen eine animierte Textur auf einem Objekt. Dies könnte z.B. eine bewegte Lavamasse sein oder irgendwas Glibbriges, was am Boden wabbelt. Oder eben in unserem Fall eine Folge von Zahlen, die wie ein Countdown aufgelistet werden. Sicherlich könnte nun jemand von Euch auf die Idee kommen, viele einzelne Texturen zu laden und diese in einem Array zu speichern. Dies mag auch durchaus sinnvoll sein nicht jedoch, wenn es sich um kleine Bilder handelt (bei uns z.B. 32x32 Pixel).&lt;br /&gt;
&lt;br /&gt;
Auch bei Bitmap-Fonts würde man nie auf die Idee kommen, für jeden Buchstaben eine einzelne Textur zu verwenden, sondern vielmehr eine Textur mit allen Buchstaben darauf erstellen, da dies u.a. den Ladevorgang erheblich beschleunigt! Klingt einleuchtend oder? Aber wie sollen wir dem Programm mitteilen, welcher Teil der Textur auf welche &amp;quot;Ecke&amp;quot; geklebt werden soll? Nun... auch hierbei heißt des Lösungs Rätsel [Anm. des Lektors: Er macht's schon wieder. Herrlich...] UV-Mapping!&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers.gif]]&lt;br /&gt;
&lt;br /&gt;
Dies ist unsere Textur! Sie hat eine Gesamtlänge von 256x32 Bildpunkten und wie man leicht sehen kann, soll sie aus 8 Teilstücken bestehen. Die V-Koordinate können wir in diesem Fall getrost vernachlässigen, weil sie in diesem Fall immer konstant sein wird, weil wir die ganze Höhe der Textur verwenden wollen. Sie wäre nur dann interessant, wenn wir z.B. noch eine zweite Reihe darunter setzen würden. Ich denke jedoch, dass jemand der das gleich folgende verstanden hat, sofort eine Lösung für diese &amp;quot;Problematik&amp;quot; finden wird ;).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers2.gif]]&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass wir uns bewusst werden, dass eine Textur beim UV-Mapping immer von 0 bis 1 reicht. Um nun die einzelnen Bilder aus einer Textur auf ein Objekt zu setzen, müssen wir nichts anderes machen, als zu errechnen, an welcher Stelle ein Bild anfängt und wo es aufhört. Nur zur Kontrolle, damit es auch jeder begreift: Würden wir nur die erste Hälfte der Textur auf ein Objekt kleben, so müsste unsere U-Koordinate von 0 bis 0.5 reichen. Die zweite Hälfte hingegen von 0.5 - 1.0. Soweit klingt es doch noch alles logisch oder?&lt;br /&gt;
&lt;br /&gt;
Genauso müssen wir auch vorgehen, wenn wir einzelne Bilder auf einem Quad abbilden wollen. In unserem Fall müsste die U-Koordinate von 0 bis 1/8 reichen. Das zweite Bildchen hingegen von 1/8 bis 2/8 etc. D.h. wir wissen, dass jedes unserer Bilder 1/8 &amp;quot;Einheiten&amp;quot; lang ist! Und somit haben wir ja bereits eine Lösung für unser Problem. Um das ganze dynamisch auszudrücken: Wir brauchen nur die Größe der Textur durch die Anzahl der Bilder zu teilen. Bevor jemand einen Denkfehler macht: Es ist hierbei ganz egal, wie groß die Textur wirklich ist (hier 256x32 Pixel). Dank OpenGL errechnen wir das UV-Mapping ja in absoluten Größen.&lt;br /&gt;
Nun der Code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;PicLength:= 1 / PicCount;&lt;br /&gt;
PicPos:=Round(Pic)*PicLength;&lt;br /&gt;
glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(PicPos,		    1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 0); glVertex3f(1,-1,0);&lt;br /&gt;
  glTexCoord2f(PicPos,		    0); glVertex3f(-1,-1,0);&lt;br /&gt;
glEnd;&lt;br /&gt;
&lt;br /&gt;
Pic:=Pic + MovementValue;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pic ist in diesem Fall eine Variable vom Typ Single, die langsam erhöht wird. Wir runden den Wert hier, so dass beim Erreichen eines jeden ganzzahligen Wertes das nächste Bild angezeigt wird. Wir multiplizieren die Nummer des anzuzeigenden Bildes mit der Breite eines Bildes, um die Anfangsposition zu erhalten und addieren dann noch eine volle Bildbreite dazu, um die Endposition zu erhalten. Hört sich gewaltig gefährlich an, liegt aber mehr an meinem mangelnden Ausdruck als an der Schwierigkeit dieses Problems ;).&lt;br /&gt;
&lt;br /&gt;
Im Sample werdet Ihr noch sehen, was passiert, wenn man den Wert nicht rundet. Man erhält in diesem Fall einen &amp;quot;flüssigen&amp;quot; Bildübergang. Letztendlich gibt es viele Möglichkeiten, solche Ideen zu implementieren. Nehmt dies einfach als kleineren Gedankenschub und vor allem: Werdet Euch bewusst, was genau dort passiert! Eine Menge toller Dinge lassen sich mit einem guten UV-Mapping erzielen.&lt;br /&gt;
Wer noch etwas umherexperimentieren will kann gern versuchen selbes Ziel mit Hilfe der Texturenmatrix zu erreichen. Die Lösung ist verblüffend einfach.&lt;br /&gt;
&lt;br /&gt;
===Terraforming mal anders===&lt;br /&gt;
Relativ lange habe ich nach einem guten Beispiel für folgende Problematik gesucht: Ich wollte Euch die UV-Koordinaten etwas näher bringen und Euch zeigen, wofür man sie einsetzen kann. Irgendwie wollte mir nichts Interessantes aus meinem Kopf entspringen bis ich irgendwann in einigen alten Programmen von mir rumgewühlt habe und einen alten Terrainrenderer von mir fand. Schon war die Idee da! Wir schreiben ein kleines Programm, das eine ganz simple, unoptimierte Landschaft rendern wird. Das hört sich sicherlich Anfangs relativ gewaltig an, mit etwas Verständnis für die oberen Probleme sollte dies jedoch kein Problem für Euch sein.&lt;br /&gt;
&lt;br /&gt;
Zuvor allerdings ein paar Gedankenspiele. Zunächst widmen wir uns kurz der Texturiering. Wie würde die simpelste Landschaft aussehen, die wir uns vorstellen können? Richtig! Sie wäre ein einfaches, flach liegendes Quadrat mit einer Textur überzogen, der Wand aus unserem ersten Versuch sehr ähnlich! Dies hat jedoch einen klitzekleinen Nachteil: Wir könnten keine Höhenstufen einbauen und ohne die wäre die Landschaft nur halb so realistisch. Denn wir wollen versuchen, folgende Szene zu zaubern:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscape.gif|thumb|256px|none|eine Lanschaft]]&lt;br /&gt;
Um allerdings Höhen einzubinden, müssen wir die Landschaft in viele kleinen Quads unterteilen, die natürlich an Ihren Eckpunkten unterschiedliche Höhen haben, sich jedoch jeweils einige Punkte teilen. Es versteht sich von selbst, dass diese die gleiche Höhe haben müssen, damit die Landschaft auch durchgängig ist und nicht irgendwelche mysteriösen Löcher darauf erscheinen ;).&lt;br /&gt;
Auf folgendem Screenshot kann man dies deutlich erkennen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landwire.gif|thumb|256px|left|Gitter Ansicht der Landschaft]]&lt;br /&gt;
Technisch gesehen ist das Ganze einfach zu realisieren, da wir nur begreifen müssen, dass alle Quads nebeneinander liegen und sich - bis auf die äußeren alle einen Eckpunkt teilen. Nun müssen wir beim Rendern jeden Eckpunkt nur noch vom angrenzenden Quad lesen und fertig ist die Landschaft. Ich will da nicht näher drauf eingehen, weil es sich hier nicht um ein Tutorial zur Landschaftsgestaltung handelt. Der Code sollte sich eigentlich von selbst erklären.&lt;br /&gt;
&lt;br /&gt;
Vielmehr sollten wir uns einer anderen Problematik widmen! Nämlich wie zur Hölle texturieren wir die Landschaft so, dass sie nicht zur Marke &amp;quot;augenfeindlich&amp;quot; gehört?&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscapeerror.gif|thumb|256px|right|wiederkehrende Landschaft]]&lt;br /&gt;
Wenn Euer erster Gedanke dabei &amp;quot;Boah, cool!&amp;quot; ist, dann gibt's eins auf die Finger! Das wollen wir doch nicht... wie sieht den die Landschaft aus. Eine immer wiederkehrende Landschaft -&amp;gt; man erkennt sofort, dass wir hierbei auf jedes Quad die gleiche Textur geklebt haben. Doch wie schaffen wir es nun, dass wir eine Textur über alle Quads ziehen, so dass die ganze Landschaft mit einer Textur überzogen ist anstatt nur über ein einzelnes Feld?&lt;br /&gt;
Nun, des Lösungs Geheimnis [Anm. des Lektors: Ich liebe ihn dafür! Andere lösen Rätsel. Er geheimnist Lösungen] sind eben unsere UV-Koordinaten und einige pfiffige Köpfe unter Euch sollten bereits einen ersten Verdacht haben. Denn die erste Idee sollte es sein, den linken unteren Punkt eine UV-Koordinate von (0/0) zu geben und der rechten oberen (1/1).&lt;br /&gt;
Alles was wir nun also machen müssen, ist, uns die entsprechenden UV-Koordinaten für die Quads dazwischen auszurechnen und sie dann den Punkten zuzuweisen. Dafür benötigen wir zunächst die Breite eines Quads. Mit normaler Logik lässt sich folgende Aussage aufstellen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;qw:=1 / XCount&lt;br /&gt;
qh:=1 / YCount;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Ein Quad benötigt die Länge von 1 durch die Anzahl der Quads in einer Reihe oder Spalte. Genauso verhält es sich auch mit der Höhe. Nun brauchen wir beim Rendern nur noch dem jeweiligen Quad in einer For-Schleife die entsprechende Koordinate zuzuweisen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;U:=1 / XCount;&lt;br /&gt;
V:=1 / YCount;&lt;br /&gt;
&lt;br /&gt;
for y:=0 to YCount-1 do&lt;br /&gt;
begin&lt;br /&gt;
  glPushMatrix;&lt;br /&gt;
  for x:=0 to XCount-1 do&lt;br /&gt;
  begin&lt;br /&gt;
    glBegin(GL_QUADS);&lt;br /&gt;
      glTexCoord2f(U*x,     V*(y+1)); &lt;br /&gt;
      glVertex3f(0,  Map[x,y+1],  0);&lt;br /&gt;
      glTexCoord2f(U*x,     V*y);     &lt;br /&gt;
      glVertex3f(0,  Map[x,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*y);     &lt;br /&gt;
      glVertex3f(1,  Map[x+1,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*(y+1));  &lt;br /&gt;
      glVertex3f(1, Map[x+1,y+1],  0);&lt;br /&gt;
    glEnd;&lt;br /&gt;
    glTranslatef(1,0,0);&lt;br /&gt;
  end;&lt;br /&gt;
  glPopMatrix;&lt;br /&gt;
  glTranslatef(0,0,-1);&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Das sieht nach einem herben Stück Arbeit aus oder? Aber wenn Ihr Euch das ganze mal aufzeichnet und im Kopf durchspielt, wird der Groschen fallen. Denkt mal etwas darüber nach! Wenn es dann doch noch Probleme mit dem Verständnis geben sollte, wird das nächste Kapitel hoffentlich jedes Missverständnis aus dem Wege räumen ;).&lt;br /&gt;
&lt;br /&gt;
==Nachwort==&lt;br /&gt;
Okay... ich hoffe Ihr fühlt Euch nach der Abarbeitung dieses Tutorials genauso wie ich, nachdem ich es für Euch geschrieben habe... nämlich elend. Irgendwie wurde das immer mehr und ich sagte mir immer wieder &amp;quot;nein, dass ist nicht genug. Das muss genauer und anschaulicher werden&amp;quot;. Dies ist auch der Grund dafür, warum dieses eines der größten Tutorials mit den meisten Bildern usw geworden ist. Erst sollte es noch etwas mehr werden und dann in mehrere Tutorials aufgespaltet werden, allerdings glaube ich mit diesem Tutorial einen guten Mittelweg zwischen Information und Totlabern gefunden zu haben. Lasst es mich wissen, wie Ihr dazu steht!&amp;lt;br&amp;gt;&lt;br /&gt;
Und bevor die Kritiker gleich wieder alle aus Ihren Löchern kommen und mir sagen, dass einige Bereich einfach als gegeben angenommen werden; denen sei nur gesagt, dass wir u.a. auch versuchen Rücksicht auf Leute zu nehmen, die noch nie 3D programmiert haben und vielleicht Eurem Wissen nicht standhalten können. Daher halte ich es hier für wichtiger, Grundlagen wie UV-Koordinaten und den Einsatz von Texturen zu erklären, als ihnen tausende von Zeilen um die Ohren zu hauen, wie sie die Bytes von der Festplatte in den Arbeitsspeicher laden können. Um jedoch keine Wissenslöcher offen zu lassen: Ihr könnt Euch sicher sein, dass spezielle Tutorials folgen werden, die sich speziell mit dem Laden verschiedener Formate beschäftigen und die genaue Interna (was im Hintergrund abläuft) zu erklären versuchen. Auch das Alpha Blending wird hier mehr zu &amp;quot;Show-Zwecken&amp;quot; verwendet und wird zusammen mit dem Z-Buffer genauer erklärt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Also bloß keine falsche Hektik! Ich weiß ... einige von Euch sind recht ungeduldig, aber ständiges Nachfragen und Drängeln führt zu nichts. Versucht Fragen lieber ins Forum zu setzen, damit dort ein wenig Leben reinkommt. Denn wenn es dort belebter wird, kommen auch schneller neue Leute und vielleicht sind ja auch welche dabei, die dann das DGL-Team entlasten können. Also nutzt bitte das Forum, anstatt andauernd per ICQ oder Mail irgendwelche Fragen zu stellen! Die Antwort wird auch nicht viel länger auf sich warten lassen. Im Forum jedoch ist alles dokumentiert und auch anderen zugänglich, so dass ich nicht die gleiche Frage bis zu 5 mal am Tag beantworten muss. Sorry aber das geht einem auf die Nerven und vor allem auf die Zeit ;). Schließlich sind wir keine Maschinen sondern Menschen, die auch ein privates Leben haben ^__-.&lt;br /&gt;
&lt;br /&gt;
Glaubt uns, wir investieren einen sehr großen Teil unserer Zeit in dieses Projekt und solch ein Tutorial lässt sich nicht binnen weniger Tage anfertigen. Jeder der so etwas bereits einmal gemacht hat, wird wissen was ich meine. Es muss ein Konzept her, es müssen Samples geschrieben, Screenshots gemacht werden und ein halbwegs verständlicher Text her. Und nichtsdestotrotz soll es am Ende auch noch passen, einem möglichst großen Publikum Wissen vermitteln, am Besten von Schreib- und Sprachfehlern befreit und in einem halbwegs ansehnlichen HTML-Dokument präsentiert werden. Ein langer Weg ;).&lt;br /&gt;
Okay, in diesem Sinne, bis bald ;)!&lt;br /&gt;
btw: Vielen Dank an Magellan für die Bereitstellung und Integration seiner &amp;quot;besonderen Lernleistung&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Euer&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_lektion3]]|[[Tutorial_lektion5]]}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Lektion4]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15373</id>
		<title>Tutorial Lektion 4</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15373"/>
				<updated>2005-12-13T20:13:10Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Ich verstehe nur &amp;quot;Renovierung&amp;quot;? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Texturen, Tapeten und Ihre Tücken=&lt;br /&gt;
&lt;br /&gt;
==Vorwort==&lt;br /&gt;
Hi Leute,&lt;br /&gt;
kaum zu glauben aber wahr. Dieses Tutorial wird ausnahmsweise mal etwas mehr Erholung sein. Zumindest am Anfang. Was wir bisher erreicht haben ist ja alles schön, nett, praktisch und auch wichtig als Grundlage aber wenn wir aus dem Fenster sehen hören wir die Vöglein zwitschern. Hö? Wir hören was sehend? Es ist tiefste Nacht? Es muss Frühling sein ^__^.&amp;lt;br&amp;gt;&lt;br /&gt;
Und was macht man da normalweise? Wir kramen herum und machen einen großen Frühjahrsputz... die Schränke abziehen und alles schön sauber und ordentlich machen. Hach... es dürstet mich richtig danach... :D (means... *würg*).&amp;lt;br&amp;gt;&lt;br /&gt;
Da unsere Tutorials bisher Gott sei Dank keine dreckige Sache waren werden wir das mit dem Saubermachen einfach mal wegfallen lassen und uns nur mit einem Tapetenwechsel begnügen. In der Tat werden wir ab jetzt unseren Tutorials mehr grafisches Gewicht zumuten. Endlich haben die blauen Dreiecke ein Ende! Ich wünsche Euch viel Spaß ;).&lt;br /&gt;
&lt;br /&gt;
==Crash-Kurs im Handwerk des Tapezierens==&lt;br /&gt;
&lt;br /&gt;
===Ich verstehe nur &amp;quot;Renovierung&amp;quot;?===&lt;br /&gt;
Ich finde es immer wieder erschreckend Leute im Internet zu treffen, die nicht wissen was eine Textur ist... ich meine, kennen keinen Kafka, keine Quantenphysik und wissen nicht einmal wo man die Systemsteuerung findet. Wie soll man solch einem Menschen erklären, was eine Textur ist?&lt;br /&gt;
Nun, am Besten fangen wir mit einem möglichst praktischen Beispiel an. Texturen sind wie... Tapeten. Wir blicken nun zu unserer linken Seite. Der Autor erwartet nun ein DirectMind-Uplink zum Empfangen der visuellen Bildsignale. Dort haben wir eine schöne Wand... quadratisch in ihrer Form. Wollen wir diese mit einer Tapete verzieren, gehen wir in den nächsten Baumarkt, suchen uns eine hübsche aus und bringen diese an der Wand an. Natürlich haben wir eine Große geholt, und fangen nicht mit kleinen Streifen an.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn dann alles geklappt hat stehen wir vor dieser Wand und begutachten die Tapete in voller Pracht direkt vor uns. Wir haben die Wand texturiert. Streng genommen machen wir auch bei OpenGL nichts anderes, als ein Bild zu laden und dieses auf eine Fläche zu kleben. Wir werden uns jedoch auf Dauer nicht damit begnügen immer nur quadratische Flächen zu texturieren, sondern durchaus auch mal Dreiecke oder andere Vielecke. Und auch hat man uns Werkzeuge in die Hand gegeben um diese Textur noch nachträglich an der Wand zu verschieben ohne dass wir sie abnehmen müssen. Ist doch super. Es lebe die virtuelle Welt!&lt;br /&gt;
&lt;br /&gt;
===Tapezieren leicht gemacht!===&lt;br /&gt;
Okay, wir haben lange genug um den heißen Brei herumgeredet und sollten uns nun endlich auf die Arbeit stürzen. Jeder von uns sollte in der Lage sein, ein Quadrat in OpenGL genau vor unserer Nase zu erzeugen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_nonetex.gif|thumb|256px|left|Leeres Quadrat]]&lt;br /&gt;
Spätestens nun sollte die gleiche Frage aufkommen, wie bei jedem, der zum ersten Mal versucht, eine Tapete an die Wand zu bringen: &amp;quot;Wie rum muss ich das Ding da befestigen?&amp;quot;. Immerhin müssen wir uns nicht um den Leim kümmern, das erledigt unsere Grafikkarte bzw. OpenGL für uns ;).&lt;br /&gt;
&lt;br /&gt;
Wer noch nie 3D programmiert hat, wird im ersten Moment vielleicht fälschlicherweise denken, dass man die Position der Textur per Weltkoordinaten definiert. Das hätte allerdings fatale Folgen, sobald sich das Objekt im Raum bewegt. Wir müssten die Position jedes mal neu berechnen. Um eben dieses Problem zu umgehen, geht man in der 3D-Programmierung einen anderen Weg. Man vergibt einfach für jede Ecke eines Objektes eine Koordinate der Textur. OpenGL errechnet dann aus diesen Texturkoordinaten das Stück der Textur, das dann über das gesamt Objekt projiziert wird.&lt;br /&gt;
&lt;br /&gt;
Die Rede ist hierbei vom so genannten UV-Mapping, welches vor allem bei Anfängern ein leichtes Gefühl des Unbehagens auslösen sollte. Es ist jedoch nur halb so wild, wenn man es halbwegs verstanden hat.&lt;br /&gt;
&lt;br /&gt;
Betrachten wir gleich mal folgendes Bild und versuchen, uns in die Problematik hineinzuversetzen. Da Texturen unterschiedliche Größen haben können wurden so genannte Texturkoordinaten eingeführt. Es ist total egal, wie groß eine Textur ist, da sie nur einen Wertebereich von 0 bis 1 haben kann. Das heißt, wenn eine Textur 256x256 groß ist und eine andere 512x512, so haben beide eine maximale Größe von 1. Wir brauchen also das UV-Mapping nicht verändern, selbst wenn ein Objekt eine neue Textur mit anderer Größe erhält!&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Auf diesem Bild sehen wir zum einen die Textur, die wir verwenden wollen, zum anderen das Objekt, auf des &amp;quot;geklebt&amp;quot; werden soll. Natürlich sieht das in der Realität nicht so aus, ich denke aber diese Darstellung erleichtert das Verstehen ;).&lt;br /&gt;
&lt;br /&gt;
Der untere linke Bereich der Textur trägt die Texturkoordinaten von (0 / 0) (d.h. u = 0 und v = 0), der obere linke Bereich (0 / 1), der obere rechte Teil (1 / 1) und schließlich der untere rechte Bereich (1 / 0). Das heißt, alles was wir machen müssen, um auf unser Objekt eine Textur zu kleben, ist dem jeweiligen Eckpunkt unseres Quadrates die entsprechende Texturkoordinate zuzuweisen. Wobei in diesem Sinne korrekt in Anführungszeichnen stehen sollte. Es gibt kein falsches UV-Mapping! Man kann tolle Sachen mit diesen Textur-Koordinaten machen und so z.B. auch eine Textur auf einem Objekt spiegeln. Dafür müssten wir in unserem Beispiel nur die linken und rechten UV-Mapping vertauschen und z.B. für den zweiten Punkt die Koordinaten von (1 / 1) setzen und dafür beim dritten (0/ 1). Genauso würden wir auch die unteren vertauschen. Die UV-Koordinaten, wie sie oben angegeben sind, bedeuten nur, dass die Textur, so wie sie in der Datei vorkommt, auch auf das Objekt geklebt wird. Selbstverständlich ist es auch möglich eine Textur gekachelt aufkleben indem Ihr Texturkoordinaten &amp;gt; 1 vergebt, ebenso wie es möglich ist nur Teile einer Textur zu verwenden. Spielt ruhig ein wenig damit herum, und schaut Euch an was passiert! Auf einige tolle Spielerei kommen wir zum Schluss noch mal zurück :).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv_02.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Sicherlich brennt es einigen von Euch nun bereits unter den Finger und Ihr fragt &amp;quot;wie kann ich denn die UV-Koordinaten den Eckpunkten der Fläche zuweisen?&amp;quot;. Nun, zunächst funktioniert das ähnlich wie bei allen Dingen unter OpenGL. Wir setzen eine UV-Koordinate und solange wir nichts verändern, werden alle Punkte mit diesen Koordinaten versehen, bis wir andere Instruktionen geben. In unserem Fall müssen wir dies natürlich nach jedem Punkt machen. Die Funktion, die dafür verwendet wird heißt glTexCoord. Um also eine Textur auf unserem Quad zu projizieren, benötigen wir folgenden Code:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;!-- Zeilen umbrüche sind drinnen damit das Bild nicht die Code-Boc verunstaltet --&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(0,0); glVertex3f(-1,-1,0);&lt;br /&gt;
  glTexCoord2f(0,1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(1,1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(1,0); glVertex3f(1,-1,0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das klappt doch wunderbar oder? Damit wir die Textur aber auch wirklich genießen können müssen wir Texturing mit Hilfe von glEnable und dem Token GL_TEXTURE_2D aktivieren. Mit Hilfe von glDisable und demselben Token ist es dann auch möglich Objekte zu Zeichnen, die über keine Texturen verfügen. Andernfalls würde nämlich die zuletzt gesetzte Textur und die Texturkoordinaten des letzten glTexCoord-Aufrufs verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Doch eine Kleinigkeit habe ich Euch nun doch noch verschwiegen! Wir müssen natürlich noch die richtige Textur setzen, damit OpenGL überhaupt weiß, was auf diesem Quad gezeichnet werden soll. Dies ist an sich noch relativ einfach, allerdings müssen wir diese auch noch in den Speicher bekommen, damit sie überhaupt zur Verfügung steht. Nun wird's theoretisch ;).&lt;br /&gt;
&lt;br /&gt;
===Tapeten besorgen===&lt;br /&gt;
Ich werde jetzt nicht näher darauf eingehen, wie man Texturen erstellt, vielleicht gibt's ja einige Photoshop-Experten unter Euch, die Lust haben, einige Ihrer Tricks den anderen in Form eines Tutorials zu zeigen?&lt;br /&gt;
&lt;br /&gt;
Zunächst einmal müssen wir die uns die eigentlichen Bilddaten besorgen. Wir werden das jetzt in diesem Tutorial mit [[SDL]] machen es gibt jedoch auch die möglichkeit die Daten manuell zu laden das könnt ihr hier nachlesen:&lt;br /&gt;
* [[TGA Bilder laden]]&lt;br /&gt;
Es gibt allerdings auch Textur loader die euch die nächsten Kapitel abnehmen und das alles für euch machen. glBitmap ist so ein Loader, mehr dazu erfahrt ihr in dem [[Glbitmap_loader|glBitmap]]-Artikel.&lt;br /&gt;
&lt;br /&gt;
Bei SDL rufen wir nur [[IMG_Load]] auf und prüfen dann ob das Laden erfolgreich war. Hierbei sei erwähnt, dass es unter Linux zu Problemen führen kann, wenn ein Programm nicht aus einer Konsole heraus gestartet wurde. In diesem Fall sind die Pfade zu den Texturen nämlich falsch gesetzt und das Laden würde fehlschlagen. Abhilfe schafft man durch das Verwenden von absoluten Pfaden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;uses SDL, SDL_Image;&lt;br /&gt;
&lt;br /&gt;
var &lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load(ExtractFileDir(paramStr(0))+'/wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das war es dann auch schon... wir haben die Textur im Speicher Doch was nun?&lt;br /&gt;
&lt;br /&gt;
===Texturen richtig zubereitet===&lt;br /&gt;
Nachdem sich unsere Textur nun im Speicher des Computers befindet, geht es darum, daraus auch eine richtige Textur zu machen, damit wir diese in OpenGL anzeigen können. Bisher befinden sich ja nur die Rohdaten im Speicher! Hierfür teilen wir OpenGL mit, dass wir eine neue Textur erzeugen wollen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glGenTextures(1, @TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TexID ist in diesem Fall ein gluInt, kann aber genauso gut ein Array davon sein, um mehrere Texturen zu erzeugen. Genau dafür wird dann auch der erste Parameter verwendet, der OpenGL mitteilt, wie viele Texturen in dieses Array geschrieben werden sollen. In unserem Fall ist dies eben nur ein Element. Aber was ist ist das für ein Wert in TexID? OpenGL verwaltet die Texturen anhand eindeutiger Namen. glGenTextures ermittelt einen oder mehrere bisher ungenutzte Namen und schreibt diese in TexID. Durch TexId können wir unsere Textur ab sofort also eindeutig identifizieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBindTexture(GL_TEXTURE_2D, TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir teilen OpenGL mit, dass sich von nun an alle Änderungen und Anweisungen, die sich auf Texturen beziehen auf die Textur TexID beziehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die folgenden beiden Zeilen sind zwar nicht wirklich nötig, um eine Textur zu erzeugen aber glaubt mir, sie werden ansonsten potthässlich aussehen. Wir werden in einem anderen Tutorial näher auf dessen Bedeutung eingehen, nämlich den so genannten Textur-Filtern. Die momentane Einstellung ist leicht rechenlastig, jedoch auch von recht guter Qualität. Ihr werdet anfangs keine Probleme mit der Geschwindigkeit bekommen ;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu guter letzt werden müssen wir die Bildinformationen in unserem TBitmap-Objekt irgendwie OpenGL mitteilen. Dies übernimmt die Funktion glTexImage2D:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Parameter steht für den Typ der Textur. Die Dimension des Typs muss hier mit der des Befehls übereinstimmen (glTexImage2D erlaubt also nur GL_TEXTURE_2D). Der zweite Parameter gibt die Nummer des Level of Detail (LoD) an. Für den Anfang reicht hier der Level 0. Der dritte Parameter gibt an, wie viele Farbkomponenten in dem Bild enthalten sind (1-4). Die zwei folgenden Parameter übermitteln OpenGL die Breite und die Höhe des Bildes. Der sechste Parameter gibt die Breite des Rahmens an. Im siebenten Parameter wird das Format verlangt, in welcher Reihenfolge die einzelnen Farbkomponenten gespeichert sind. Bei Bitmaps ist das immer die Reihenfolge Blau, Grün, Rot. Der Typ, der einzelnen Farbwerte muss im 8. Parameter angegeben werden. Letztendlich müssen im 9. Parameter nur noch die Bildpunkte selbst übergeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit Hilfe dieser Funktion sollten nur Texturen der Größe 2^n x 2^n erzeugt werden. Andernfalls werdet Ihr die Textur nicht in Ihrer vollen Schönheit, d.h. überhaupt nicht betrachten können. Es gibt jedoch Möglichkeiten Texturen zu laden, die nicht die Größe 2^n entsprechen. Die Funktion [[gluBuild2DMipmaps]] bildet hier beispielsweise eine Alternative.&amp;lt;br&amp;gt;&lt;br /&gt;
Das war es auch schon. Wer mehr über die einzelnen Parameter und Befehle wissen will ist herzlich eingeladen in unserem Wiki umherzustöbern und sein Wissen zu erweitern um später selbst vielleicht einmal ein paar Artikel im Wiki zu veröffentlichen.&lt;br /&gt;
&lt;br /&gt;
Die Daten im Arbeitsspeicher brauchen wir nun nicht mehr. Bei SDL geben wir sie so frei:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;SDL_FreeSurface(tex);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fassen wir das ganze bei SDL nochmal zusammen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;var&lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load('./wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin		&lt;br /&gt;
    glGenTextures(1, @texture);&lt;br /&gt;
    glBindTexture(GL_TEXTURE_2D, texture);&lt;br /&gt;
		&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
		&lt;br /&gt;
    // Achtung! Einige Bildformate erwarten statt GL_RGB, GL_BGR. Diese Konstante fehlt in den Standard-Headern&lt;br /&gt;
    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&lt;br /&gt;
&lt;br /&gt;
    SDL_FreeSurface(tex);&lt;br /&gt;
  end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kommt aber bitte nicht auf die Idee die Textur in euerer Hauptschleife wieder und wieder neu zu laden. Es reicht die Textur einmal zu laden und von da an steht sie einem solange zur Verfügung bis man gedenkt sie wieder aus dem Grafikkartenspeicher zu entfernen.&amp;lt;br&amp;gt;&lt;br /&gt;
Das übernimmt die Funktion [[glDeleteTextures]]. glDeleteTextures funktioniert ähnlich wie [[glGenTextures]], nur dass die Texturen entfernt werden. Der erste Parameter gibt die Anzahl der zu löschenden Texturen an, während der zweite Parameter den Namen der Textur bzw. ein Array der Namen mehrerer Texturen verlangt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das ist doch für den Anfang nicht schlecht. Ihr solltet nun in der Lage sein, zumindest einfache Objekte zu texturieren. Das ist eigentlich das gesamte Grundprinzip. Natürlich gestaltet es sich schwieriger, ein komplexeres Objekt mit UV-Koordinaten zu versehen, als ein Quad, aber an der Technik selbst ändert sich nur wenig. Wir werden nun einige Spielereien zeigen, die man mit Texturen machen kann, damit Ihr ein Gefühl dafür bekommt, wie man ein Problem elegant umschiffen kann!&lt;br /&gt;
&lt;br /&gt;
==Die Rückkehr der Matrizen==&lt;br /&gt;
===Texturen===&lt;br /&gt;
Tja... und da ich ein Sadist bin [Anm. des Lektors: Ooooh ja!] werden wir uns nun nochmals den Matrizen zuwenden! Dachtet Ihr etwa, Ihr seid die Dinger schon wieder los? Ich habe Euch im letzten Tutorial angedroht, dass es nicht nur eine Matrix für die &amp;quot;Welt&amp;quot; gibt, sondern auch noch weitere. Unter anderem eben auch für Texturen.&lt;br /&gt;
&lt;br /&gt;
Die Texturmatrix funktioniert streng genommen genauso wie auch die Worldmatrix. Solange wir sie aktiv haben, wird sie von jedem Matrixbefehl berücksichtigt! Einziger wirklicher Unterschied ist, dass sie nicht die Position oder die Form eines Objektes beeinflusst, sondern nur das Rendern der Textur selbst. Hö? Was meint der Kerl bloß damit?! Nun... stellt Euch vor, Ihr habt ein Quad und wollt darauf eine Textur bewegen, so dass es aussieht, als würde sie sich von rechts nach links bewegen! Was wir jedoch nicht wollen ist, dass sich das Objekt bewegt, sondern nur, das was darauf zu sehen ist. Stellt Euch vor, Ihr schaut aus einem Fenster und seht einen wolkigen Himmel, der Wind bläst die Wolken von einer Himmelsrichtung zur anderen. Ihr könntet so z.B. das Fenster als Quad nehmen und dann die Textur darauf zeichnen und glaubt mir, die Illusion würde auffliegen, sobald sich das Fenster mit der Textur bewegen soll. Nein, stattdessen bewegen wir nur die Textur auf dem Quad und zwar ohne das UV-Mapping anzutasten. Wir beeinflussen einfach die Art, wie die Textur auf das Quad projiziert werden soll. Dafür dient die Texturmatrix.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns mal vor, dass wir unser Quad zeichnen und eine Variable X haben, die wir bei jedem Rendervorgang leicht erhöhen. Dies soll die Bewegung darstellen. Alles was wir nun tun müssen ist, die Texturmatrix entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glMatrixMode(GL_TEXTURE);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  glTranslatef(x,0,0);&lt;br /&gt;
glMatrixMode(GL_MODELVIEW);&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist bereits der ganze Spuk! Wir teilen OpenGL durch glMatrixMode mit, dass sich ab sofort alle Veränderungen der Matrix nur noch auf die Texturmatrix beziehen sollen. Danach setzen wir diese sofort auf ihren Standardwert zurück. Der Grund hierfür sollte Euch von der Worldmatrix noch in Erinnerung sein. Anschließend ändern wir die Position der Textur auf dem Quad. Würden wir X jedes Mal um 1 Einheit erhöhen, so würde diese Operation ohne Effekt bleiben, da wir die Textur immer um ihre ganze Größe nach links projizieren würden. Würden wir X z.B. bei jedem Vorgang um 0.01 erhöhen, so würde die Textur sich langsam von rechts nach links bewegen. Ich denke, Ihr könnt bereits erahnen, welche Parameter dafür verwendet werden, um eine Textur von unten nach oben zu bewegen ;).&lt;br /&gt;
&lt;br /&gt;
Wichtig ist auf jeden Fall, dass Ihr anschließend mit glMatrixMode wieder die Worldmatrix aktiviert, da sonst alle weiteren Matrixmanipulationen auf die Texturmatrix angewandt werden würden. Denkt nicht, dass die Texturmatrix damit deaktiviert wird! Ab sofort wird auf das Objekt sowohl die World- als auch die Texturmatrix angewendet. Seht Ihr? Das Ganze ist doch gar nicht ganz so schlimm. Es versteht sich auch von selbst, dass Ihr glRotate und glScale ebenfalls darauf anwenden könnt, natürlich auch nach den gleichen Regeln auf die Worldmatrix. Experimentiert am Besten auch etwas mit diesen Einstellungen herum!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wir tapezieren unsere Welt mal anders==&lt;br /&gt;
===Am Fließband===&lt;br /&gt;
Eigentlich sollte an dieser Stelle bereits Schluss sein. Ich wurde allerdings während des Schreibens des Tutorials nach einer Sache gefragt und möchte die Chance nutzen, diese Frage zu beantworten und gleichzeitig das angewandte Wissen der vorhergehenden Lektion etwas zu vertiefen. &lt;br /&gt;
&lt;br /&gt;
Wir haben folgende Problematik: Wir brauchen eine animierte Textur auf einem Objekt. Dies könnte z.B. eine bewegte Lavamasse sein oder irgendwas Glibbriges, was am Boden wabbelt. Oder eben in unserem Fall eine Folge von Zahlen, die wie ein Countdown aufgelistet werden. Sicherlich könnte nun jemand von Euch auf die Idee kommen, viele einzelne Texturen zu laden und diese in einem Array zu speichern. Dies mag auch durchaus sinnvoll sein nicht jedoch, wenn es sich um kleine Bilder handelt (bei uns z.B. 32x32 Pixel).&lt;br /&gt;
&lt;br /&gt;
Auch bei Bitmap-Fonts würde man nie auf die Idee kommen, für jeden Buchstaben eine einzelne Textur zu verwenden, sondern vielmehr eine Textur mit allen Buchstaben darauf erstellen, da dies u.a. den Ladevorgang erheblich beschleunigt! Klingt einleuchtend oder? Aber wie sollen wir dem Programm mitteilen, welcher Teil der Textur auf welche &amp;quot;Ecke&amp;quot; geklebt werden soll? Nun... auch hierbei heißt des Lösungs Rätsel [Anm. des Lektors: Er macht's schon wieder. Herrlich...] UV-Mapping!&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers.gif]]&lt;br /&gt;
&lt;br /&gt;
Dies ist unsere Textur! Sie hat eine Gesamtlänge von 256x32 Bildpunkten und wie man leicht sehen kann, soll sie aus 8 Teilstücken bestehen. Die V-Koordinate können wir in diesem Fall getrost vernachlässigen, weil sie in diesem Fall immer konstant sein wird, weil wir die ganze Höhe der Textur verwenden wollen. Sie wäre nur dann interessant, wenn wir z.B. noch eine zweite Reihe darunter setzen würden. Ich denke jedoch, dass jemand der das gleich folgende verstanden hat, sofort eine Lösung für diese &amp;quot;Problematik&amp;quot; finden wird ;).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers2.gif]]&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass wir uns bewusst werden, dass eine Textur beim UV-Mapping immer von 0 bis 1 reicht. Um nun die einzelnen Bilder aus einer Textur auf ein Objekt zu setzen, müssen wir nichts anderes machen, als zu errechnen, an welcher Stelle ein Bild anfängt und wo es aufhört. Nur zur Kontrolle, damit es auch jeder begreift: Würden wir nur die erste Hälfte der Textur auf ein Objekt kleben, so müsste unsere U-Koordinate von 0 bis 0.5 reichen. Die zweite Hälfte hingegen von 0.5 - 1.0. Soweit klingt es doch noch alles logisch oder?&lt;br /&gt;
&lt;br /&gt;
Genauso müssen wir auch vorgehen, wenn wir einzelne Bilder auf einem Quad abbilden wollen. In unserem Fall müsste die U-Koordinate von 0 bis 1/8 reichen. Das zweite Bildchen hingegen von 1/8 bis 2/8 etc. D.h. wir wissen, dass jedes unserer Bilder 1/8 &amp;quot;Einheiten&amp;quot; lang ist! Und somit haben wir ja bereits eine Lösung für unser Problem. Um das ganze dynamisch auszudrücken: Wir brauchen nur die Größe der Textur durch die Anzahl der Bilder zu teilen. Bevor jemand einen Denkfehler macht: Es ist hierbei ganz egal, wie groß die Textur wirklich ist (hier 256x32 Pixel). Dank OpenGL errechnen wir das UV-Mapping ja in absoluten Größen.&lt;br /&gt;
Nun der Code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;PicLength:= 1 / PicCount;&lt;br /&gt;
PicPos:=Round(Pic)*PicLength;&lt;br /&gt;
glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(PicPos,		    1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 0); glVertex3f(1,-1,0);&lt;br /&gt;
  glTexCoord2f(PicPos,		    0); glVertex3f(-1,-1,0);&lt;br /&gt;
glEnd;&lt;br /&gt;
&lt;br /&gt;
Pic:=Pic + MovementValue;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pic ist in diesem Fall eine Variable vom Typ Single, die langsam erhöht wird. Wir runden den Wert hier, so dass beim Erreichen eines jeden ganzzahligen Wertes das nächste Bild angezeigt wird. Wir multiplizieren die Nummer des anzuzeigenden Bildes mit der Breite eines Bildes, um die Anfangsposition zu erhalten und addieren dann noch eine volle Bildbreite dazu, um die Endposition zu erhalten. Hört sich gewaltig gefährlich an, liegt aber mehr an meinem mangelnden Ausdruck als an der Schwierigkeit dieses Problems ;).&lt;br /&gt;
&lt;br /&gt;
Im Sample werdet Ihr noch sehen, was passiert, wenn man den Wert nicht rundet. Man erhält in diesem Fall einen &amp;quot;flüssigen&amp;quot; Bildübergang. Letztendlich gibt es viele Möglichkeiten, solche Ideen zu implementieren. Nehmt dies einfach als kleineren Gedankenschub und vor allem: Werdet Euch bewusst, was genau dort passiert! Eine Menge toller Dinge lassen sich mit einem guten UV-Mapping erzielen.&lt;br /&gt;
Wer noch etwas umherexperimentieren will kann gern versuchen selbes Ziel mit Hilfe der Texturenmatrix zu erreichen. Die Lösung ist verblüffend einfach.&lt;br /&gt;
&lt;br /&gt;
===Terraforming mal anders===&lt;br /&gt;
Relativ lange habe ich nach einem guten Beispiel für folgende Problematik gesucht: Ich wollte Euch die UV-Koordinaten etwas näher bringen und Euch zeigen, wofür man sie einsetzen kann. Irgendwie wollte mir nichts Interessantes aus meinem Kopf entspringen bis ich irgendwann in einigen alten Programmen von mir rumgewühlt habe und einen alten Terrainrenderer von mir fand. Schon war die Idee da! Wir schreiben ein kleines Programm, das eine ganz simple, unoptimierte Landschaft rendern wird. Das hört sich sicherlich Anfangs relativ gewaltig an, mit etwas Verständnis für die oberen Probleme sollte dies jedoch kein Problem für Euch sein.&lt;br /&gt;
&lt;br /&gt;
Zuvor allerdings ein paar Gedankenspiele. Zunächst widmen wir uns kurz der Texturiering. Wie würde die simpelste Landschaft aussehen, die wir uns vorstellen können? Richtig! Sie wäre ein einfaches, flach liegendes Quadrat mit einer Textur überzogen, der Wand aus unserem ersten Versuch sehr ähnlich! Dies hat jedoch einen klitzekleinen Nachteil: Wir könnten keine Höhenstufen einbauen und ohne die wäre die Landschaft nur halb so realistisch. Denn wir wollen versuchen, folgende Szene zu zaubern:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscape.gif|thumb|256px|none|eine Lanschaft]]&lt;br /&gt;
Um allerdings Höhen einzubinden, müssen wir die Landschaft in viele kleinen Quads unterteilen, die natürlich an Ihren Eckpunkten unterschiedliche Höhen haben, sich jedoch jeweils einige Punkte teilen. Es versteht sich von selbst, dass diese die gleiche Höhe haben müssen, damit die Landschaft auch durchgängig ist und nicht irgendwelche mysteriösen Löcher darauf erscheinen ;).&lt;br /&gt;
Auf folgendem Screenshot kann man dies deutlich erkennen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landwire.gif|thumb|256px|left|Gitter Ansicht der Landschaft]]&lt;br /&gt;
Technisch gesehen ist das Ganze einfach zu realisieren, da wir nur begreifen müssen, dass alle Quads nebeneinander liegen und sich - bis auf die äußeren alle einen Eckpunkt teilen. Nun müssen wir beim Rendern jeden Eckpunkt nur noch vom angrenzenden Quad lesen und fertig ist die Landschaft. Ich will da nicht näher drauf eingehen, weil es sich hier nicht um ein Tutorial zur Landschaftsgestaltung handelt. Der Code sollte sich eigentlich von selbst erklären.&lt;br /&gt;
&lt;br /&gt;
Vielmehr sollten wir uns einer anderen Problematik widmen! Nämlich wie zur Hölle texturieren wir die Landschaft so, dass sie nicht zur Marke &amp;quot;augenfeindlich&amp;quot; gehört?&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscapeerror.gif|thumb|256px|right|wiederkehrende Landschaft]]&lt;br /&gt;
Wenn Euer erster Gedanke dabei &amp;quot;Boah, cool!&amp;quot; ist, dann gibt's eins auf die Finger! Das wollen wir doch nicht... wie sieht den die Landschaft aus. Eine immer wiederkehrende Landschaft -&amp;gt; man erkennt sofort, dass wir hierbei auf jedes Quad die gleiche Textur geklebt haben. Doch wie schaffen wir es nun, dass wir eine Textur über alle Quads ziehen, so dass die ganze Landschaft mit einer Textur überzogen ist anstatt nur über ein einzelnes Feld?&lt;br /&gt;
Nun, des Lösungs Geheimnis [Anm. des Lektors: Ich liebe ihn dafür! Andere lösen Rätsel. Er geheimnist Lösungen] sind eben unsere UV-Koordinaten und einige pfiffige Köpfe unter Euch sollten bereits einen ersten Verdacht haben. Denn die erste Idee sollte es sein, den linken unteren Punkt eine UV-Koordinate von (0/0) zu geben und der rechten oberen (1/1).&lt;br /&gt;
Alles was wir nun also machen müssen, ist, uns die entsprechenden UV-Koordinaten für die Quads dazwischen auszurechnen und sie dann den Punkten zuzuweisen. Dafür benötigen wir zunächst die Breite eines Quads. Mit normaler Logik lässt sich folgende Aussage aufstellen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;qw:=1 / XCount&lt;br /&gt;
qh:=1 / YCount;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Ein Quad benötigt die Länge von 1 durch die Anzahl der Quads in einer Reihe oder Spalte. Genauso verhält es sich auch mit der Höhe. Nun brauchen wir beim Rendern nur noch dem jeweiligen Quad in einer For-Schleife die entsprechende Koordinate zuzuweisen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;U:=1 / XCount;&lt;br /&gt;
V:=1 / YCount;&lt;br /&gt;
&lt;br /&gt;
for y:=0 to YCount-1 do&lt;br /&gt;
begin&lt;br /&gt;
  glPushMatrix;&lt;br /&gt;
  for x:=0 to XCount-1 do&lt;br /&gt;
  begin&lt;br /&gt;
    glBegin(GL_QUADS);&lt;br /&gt;
      glTexCoord2f(U*x,     V*(y+1)); &lt;br /&gt;
      glVertex3f(0,  Map[x,y+1],  0);&lt;br /&gt;
      glTexCoord2f(U*x,     V*y);     &lt;br /&gt;
      glVertex3f(0,  Map[x,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*y);     &lt;br /&gt;
      glVertex3f(1,  Map[x+1,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*(y+1));  &lt;br /&gt;
      glVertex3f(1, Map[x+1,y+1],  0);&lt;br /&gt;
    glEnd;&lt;br /&gt;
    glTranslatef(1,0,0);&lt;br /&gt;
  end;&lt;br /&gt;
  glPopMatrix;&lt;br /&gt;
  glTranslatef(0,0,-1);&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Das sieht nach einem herben Stück Arbeit aus oder? Aber wenn Ihr Euch das ganze mal aufzeichnet und im Kopf durchspielt, wird der Groschen fallen. Denkt mal etwas darüber nach! Wenn es dann doch noch Probleme mit dem Verständnis geben sollte, wird das nächste Kapitel hoffentlich jedes Missverständnis aus dem Wege räumen ;).&lt;br /&gt;
&lt;br /&gt;
==Nachwort==&lt;br /&gt;
Okay... ich hoffe Ihr fühlt Euch nach der Abarbeitung dieses Tutorials genauso wie ich, nachdem ich es für Euch geschrieben habe... nämlich elend. Irgendwie wurde das immer mehr und ich sagte mir immer wieder &amp;quot;nein, dass ist nicht genug. Das muss genauer und anschaulicher werden&amp;quot;. Dies ist auch der Grund dafür, warum dieses eines der größten Tutorials mit den meisten Bildern usw geworden ist. Erst sollte es noch etwas mehr werden und dann in mehrere Tutorials aufgespaltet werden, allerdings glaube ich mit diesem Tutorial einen guten Mittelweg zwischen Information und Totlabern gefunden zu haben. Lasst es mich wissen, wie Ihr dazu steht!&amp;lt;br&amp;gt;&lt;br /&gt;
Und bevor die Kritiker gleich wieder alle aus Ihren Löchern kommen und mir sagen, dass einige Bereich einfach als gegeben angenommen werden; denen sei nur gesagt, dass wir u.a. auch versuchen Rücksicht auf Leute zu nehmen, die noch nie 3D programmiert haben und vielleicht Eurem Wissen nicht standhalten können. Daher halte ich es hier für wichtiger, Grundlagen wie UV-Koordinaten und den Einsatz von Texturen zu erklären, als ihnen tausende von Zeilen um die Ohren zu hauen, wie sie die Bytes von der Festplatte in den Arbeitsspeicher laden können. Um jedoch keine Wissenslöcher offen zu lassen: Ihr könnt Euch sicher sein, dass spezielle Tutorials folgen werden, die sich speziell mit dem Laden verschiedener Formate beschäftigen und die genaue Interna (was im Hintergrund abläuft) zu erklären versuchen. Auch das Alpha Blending wird hier mehr zu &amp;quot;Show-Zwecken&amp;quot; verwendet und wird zusammen mit dem Z-Buffer genauer erklärt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Also bloß keine falsche Hektik! Ich weiß ... einige von Euch sind recht ungeduldig, aber ständiges Nachfragen und Drängeln führt zu nichts. Versucht Fragen lieber ins Forum zu setzen, damit dort ein wenig Leben reinkommt. Denn wenn es dort belebter wird, kommen auch schneller neue Leute und vielleicht sind ja auch welche dabei, die dann das DGL-Team entlasten können. Also nutzt bitte das Forum, anstatt andauernd per ICQ oder Mail irgendwelche Fragen zu stellen! Die Antwort wird auch nicht viel länger auf sich warten lassen. Im Forum jedoch ist alles dokumentiert und auch anderen zugänglich, so dass ich nicht die gleiche Frage bis zu 5 mal am Tag beantworten muss. Sorry aber das geht einem auf die Nerven und vor allem auf die Zeit ;). Schließlich sind wir keine Maschinen sondern Menschen, die auch ein privates Leben haben ^__-.&lt;br /&gt;
&lt;br /&gt;
Glaubt uns, wir investieren einen sehr großen Teil unserer Zeit in dieses Projekt und solch ein Tutorial lässt sich nicht binnen weniger Tage anfertigen. Jeder der so etwas bereits einmal gemacht hat, wird wissen was ich meine. Es muss ein Konzept her, es müssen Samples geschrieben, Screenshots gemacht werden und ein halbwegs verständlicher Text her. Und nichtsdestotrotz soll es am Ende auch noch passen, einem möglichst großen Publikum Wissen vermitteln, am Besten von Schreib- und Sprachfehlern befreit und in einem halbwegs ansehnlichen HTML-Dokument präsentiert werden. Ein langer Weg ;).&lt;br /&gt;
Okay, in diesem Sinne, bis bald ;)!&lt;br /&gt;
btw: Vielen Dank an Magellan für die Bereitstellung und Integration seiner &amp;quot;besonderen Lernleistung&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Euer&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_lektion3]]|[[Tutorial_lektion5]]}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Lektion4]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15372</id>
		<title>Tutorial Lektion 4</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_4&amp;diff=15372"/>
				<updated>2005-12-13T20:10:46Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Vorwort */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Texturen, Tapeten und Ihre Tücken=&lt;br /&gt;
&lt;br /&gt;
==Vorwort==&lt;br /&gt;
Hi Leute,&lt;br /&gt;
kaum zu glauben aber wahr. Dieses Tutorial wird ausnahmsweise mal etwas mehr Erholung sein. Zumindest am Anfang. Was wir bisher erreicht haben ist ja alles schön, nett, praktisch und auch wichtig als Grundlage aber wenn wir aus dem Fenster sehen hören wir die Vöglein zwitschern. Hö? Wir hören was sehend? Es ist tiefste Nacht? Es muss Frühling sein ^__^.&amp;lt;br&amp;gt;&lt;br /&gt;
Und was macht man da normalweise? Wir kramen herum und machen einen großen Frühjahrsputz... die Schränke abziehen und alles schön sauber und ordentlich machen. Hach... es dürstet mich richtig danach... :D (means... *würg*).&amp;lt;br&amp;gt;&lt;br /&gt;
Da unsere Tutorials bisher Gott sei Dank keine dreckige Sache waren werden wir das mit dem Saubermachen einfach mal wegfallen lassen und uns nur mit einem Tapetenwechsel begnügen. In der Tat werden wir ab jetzt unseren Tutorials mehr grafisches Gewicht zumuten. Endlich haben die blauen Dreiecke ein Ende! Ich wünsche Euch viel Spaß ;).&lt;br /&gt;
&lt;br /&gt;
==Crash-Kurs im Handwerk des Tapezierens==&lt;br /&gt;
&lt;br /&gt;
===Ich verstehe nur &amp;quot;Renovierung&amp;quot;?===&lt;br /&gt;
Ich finde es immer wieder erschreckend Leute im Internet zu treffen, die nicht wissen was eine Textur ist... ich meine, kennen keinen Kafka, keine Quantenphysik und wissen nicht einmal wo man die Systemsteuerung findet. Wie soll man solch einem Menschen erklären, was eine Textur ist?&lt;br /&gt;
Nun, am Besten fangen wir mit einem möglichst praktischen Beispiel an. Texturen sind wie... Tapeten. Wir blicken nun zu unserer linken Seite. Der Autor erwartet nun ein DirectMind-Uplink zum Empfangen der visuellen Bildsignale. Dort haben wir eine schöne Wand... quadratisch in ihrer Form. Wollen wir diese mit einer Tapete verzieren, gehen wir in den nächsten Baumarkt, suchen uns eine hübsche aus und bringen diese an der Wand an. Natürlich haben wir eine große geholt, und fangen nicht mit kleinen Streifen an.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn dann alles geklappt hat stehen wir vor dieser Wand und begutachten die Tapete in voller Pracht direkt vor uns. Wir haben die Wand texturiert. Streng genommen machen wir auch bei OpenGL nichts anderes, als ein Bild zu laden und dieses auf eine Fläche zu kleben. Wir werden uns jedoch auf Dauer nicht damit begnügen immer nur quadratische Flächen zu texturieren, sondern durchaus auch mal Dreiecke oder andere Vielecke. Und auch hat man uns Werkzeuge in die Hand gegeben, um diese Textur noch nachträglich an der Wand zu verschieben, ohne dass wir sie abnehmen müssen. Ist doch super. Es lebe die virtuelle Welt!&lt;br /&gt;
&lt;br /&gt;
===Tapezieren leicht gemacht!===&lt;br /&gt;
Okay, wir haben lange genug um den heißen Brei herumgeredet und sollten uns nun endlich auf die Arbeit stürzen. Jeder von uns sollte in der Lage sein, ein Quadrat in OpenGL genau vor unserer Nase zu erzeugen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_nonetex.gif|thumb|256px|left|Leeres Quadrat]]&lt;br /&gt;
Spätestens nun sollte die gleiche Frage aufkommen, wie bei jedem, der zum ersten Mal versucht, eine Tapete an die Wand zu bringen: &amp;quot;Wie rum muss ich das Ding da befestigen?&amp;quot;. Immerhin müssen wir uns nicht um den Leim kümmern, das erledigt unsere Grafikkarte bzw. OpenGL für uns ;).&lt;br /&gt;
&lt;br /&gt;
Wer noch nie 3D programmiert hat, wird im ersten Moment vielleicht fälschlicherweise denken, dass man die Position der Textur per Weltkoordinaten definiert. Das hätte allerdings fatale Folgen, sobald sich das Objekt im Raum bewegt. Wir müssten die Position jedes mal neu berechnen. Um eben dieses Problem zu umgehen, geht man in der 3D-Programmierung einen anderen Weg. Man vergibt einfach für jede Ecke eines Objektes eine Koordinate der Textur. OpenGL errechnet dann aus diesen Texturkoordinaten das Stück der Textur, das dann über das gesamt Objekt projiziert wird.&lt;br /&gt;
&lt;br /&gt;
Die Rede ist hierbei vom so genannten UV-Mapping, welches vor allem bei Anfängern ein leichtes Gefühl des Unbehagens auslösen sollte. Es ist jedoch nur halb so wild, wenn man es halbwegs verstanden hat.&lt;br /&gt;
&lt;br /&gt;
Betrachten wir gleich mal folgendes Bild und versuchen, uns in die Problematik hineinzuversetzen. Da Texturen unterschiedliche Größen haben können wurden so genannte Texturkoordinaten eingeführt. Es ist total egal, wie groß eine Textur ist, da sie nur einen Wertebereich von 0 bis 1 haben kann. Das heißt, wenn eine Textur 256x256 groß ist und eine andere 512x512, so haben beide eine maximale Größe von 1. Wir brauchen also das UV-Mapping nicht verändern, selbst wenn ein Objekt eine neue Textur mit anderer Größe erhält!&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Auf diesem Bild sehen wir zum einen die Textur, die wir verwenden wollen, zum anderen das Objekt, auf des &amp;quot;geklebt&amp;quot; werden soll. Natürlich sieht das in der Realität nicht so aus, ich denke aber diese Darstellung erleichtert das Verstehen ;).&lt;br /&gt;
&lt;br /&gt;
Der untere linke Bereich der Textur trägt die Texturkoordinaten von (0 / 0) (d.h. u = 0 und v = 0), der obere linke Bereich (0 / 1), der obere rechte Teil (1 / 1) und schließlich der untere rechte Bereich (1 / 0). Das heißt, alles was wir machen müssen, um auf unser Objekt eine Textur zu kleben, ist dem jeweiligen Eckpunkt unseres Quadrates die entsprechende Texturkoordinate zuzuweisen. Wobei in diesem Sinne korrekt in Anführungszeichnen stehen sollte. Es gibt kein falsches UV-Mapping! Man kann tolle Sachen mit diesen Textur-Koordinaten machen und so z.B. auch eine Textur auf einem Objekt spiegeln. Dafür müssten wir in unserem Beispiel nur die linken und rechten UV-Mapping vertauschen und z.B. für den zweiten Punkt die Koordinaten von (1 / 1) setzen und dafür beim dritten (0/ 1). Genauso würden wir auch die unteren vertauschen. Die UV-Koordinaten, wie sie oben angegeben sind, bedeuten nur, dass die Textur, so wie sie in der Datei vorkommt, auch auf das Objekt geklebt wird. Selbstverständlich ist es auch möglich eine Textur gekachelt aufkleben indem Ihr Texturkoordinaten &amp;gt; 1 vergebt, ebenso wie es möglich ist nur Teile einer Textur zu verwenden. Spielt ruhig ein wenig damit herum, und schaut Euch an was passiert! Auf einige tolle Spielerei kommen wir zum Schluss noch mal zurück :).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_texuv_02.gif|thumb|256px|right|Textur und leere Quadratfläche]]&lt;br /&gt;
Sicherlich brennt es einigen von Euch nun bereits unter den Finger und Ihr fragt &amp;quot;wie kann ich denn die UV-Koordinaten den Eckpunkten der Fläche zuweisen?&amp;quot;. Nun, zunächst funktioniert das ähnlich wie bei allen Dingen unter OpenGL. Wir setzen eine UV-Koordinate und solange wir nichts verändern, werden alle Punkte mit diesen Koordinaten versehen, bis wir andere Instruktionen geben. In unserem Fall müssen wir dies natürlich nach jedem Punkt machen. Die Funktion, die dafür verwendet wird heißt glTexCoord. Um also eine Textur auf unserem Quad zu projizieren, benötigen wir folgenden Code:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;!-- Zeilen umbrüche sind drinnen damit das Bild nicht die Code-Boc verunstaltet --&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(0,0); glVertex3f(-1,-1,0);&lt;br /&gt;
  glTexCoord2f(0,1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(1,1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(1,0); glVertex3f(1,-1,0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das klappt doch wunderbar oder? Damit wir die Textur aber auch wirklich genießen können müssen wir Texturing mit Hilfe von glEnable und dem Token GL_TEXTURE_2D aktivieren. Mit Hilfe von glDisable und demselben Token ist es dann auch möglich Objekte zu Zeichnen, die über keine Texturen verfügen. Andernfalls würde nämlich die zuletzt gesetzte Textur und die Texturkoordinaten des letzten glTexCoord-Aufrufs verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Doch eine Kleinigkeit habe ich Euch nun doch noch verschwiegen! Wir müssen natürlich noch die richtige Textur setzen, damit OpenGL überhaupt weiß, was auf diesem Quad gezeichnet werden soll. Dies ist an sich noch relativ einfach, allerdings müssen wir diese auch noch in den Speicher bekommen, damit sie überhaupt zur Verfügung steht. Nun wird's theoretisch ;).&lt;br /&gt;
&lt;br /&gt;
===Tapeten besorgen===&lt;br /&gt;
Ich werde jetzt nicht näher darauf eingehen, wie man Texturen erstellt, vielleicht gibt's ja einige Photoshop-Experten unter Euch, die Lust haben, einige Ihrer Tricks den anderen in Form eines Tutorials zu zeigen?&lt;br /&gt;
&lt;br /&gt;
Zunächst einmal müssen wir die uns die eigentlichen Bilddaten besorgen. Wir werden das jetzt in diesem Tutorial mit [[SDL]] machen es gibt jedoch auch die möglichkeit die Daten manuell zu laden das könnt ihr hier nachlesen:&lt;br /&gt;
* [[TGA Bilder laden]]&lt;br /&gt;
Es gibt allerdings auch Textur loader die euch die nächsten Kapitel abnehmen und das alles für euch machen. glBitmap ist so ein Loader, mehr dazu erfahrt ihr in dem [[Glbitmap_loader|glBitmap]]-Artikel.&lt;br /&gt;
&lt;br /&gt;
Bei SDL rufen wir nur [[IMG_Load]] auf und prüfen dann ob das Laden erfolgreich war. Hierbei sei erwähnt, dass es unter Linux zu Problemen führen kann, wenn ein Programm nicht aus einer Konsole heraus gestartet wurde. In diesem Fall sind die Pfade zu den Texturen nämlich falsch gesetzt und das Laden würde fehlschlagen. Abhilfe schafft man durch das Verwenden von absoluten Pfaden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;uses SDL, SDL_Image;&lt;br /&gt;
&lt;br /&gt;
var &lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load(ExtractFileDir(paramStr(0))+'/wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das war es dann auch schon... wir haben die Textur im Speicher Doch was nun?&lt;br /&gt;
&lt;br /&gt;
===Texturen richtig zubereitet===&lt;br /&gt;
Nachdem sich unsere Textur nun im Speicher des Computers befindet, geht es darum, daraus auch eine richtige Textur zu machen, damit wir diese in OpenGL anzeigen können. Bisher befinden sich ja nur die Rohdaten im Speicher! Hierfür teilen wir OpenGL mit, dass wir eine neue Textur erzeugen wollen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glGenTextures(1, @TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TexID ist in diesem Fall ein gluInt, kann aber genauso gut ein Array davon sein, um mehrere Texturen zu erzeugen. Genau dafür wird dann auch der erste Parameter verwendet, der OpenGL mitteilt, wie viele Texturen in dieses Array geschrieben werden sollen. In unserem Fall ist dies eben nur ein Element. Aber was ist ist das für ein Wert in TexID? OpenGL verwaltet die Texturen anhand eindeutiger Namen. glGenTextures ermittelt einen oder mehrere bisher ungenutzte Namen und schreibt diese in TexID. Durch TexId können wir unsere Textur ab sofort also eindeutig identifizieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBindTexture(GL_TEXTURE_2D, TexID);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir teilen OpenGL mit, dass sich von nun an alle Änderungen und Anweisungen, die sich auf Texturen beziehen auf die Textur TexID beziehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die folgenden beiden Zeilen sind zwar nicht wirklich nötig, um eine Textur zu erzeugen aber glaubt mir, sie werden ansonsten potthässlich aussehen. Wir werden in einem anderen Tutorial näher auf dessen Bedeutung eingehen, nämlich den so genannten Textur-Filtern. Die momentane Einstellung ist leicht rechenlastig, jedoch auch von recht guter Qualität. Ihr werdet anfangs keine Probleme mit der Geschwindigkeit bekommen ;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu guter letzt werden müssen wir die Bildinformationen in unserem TBitmap-Objekt irgendwie OpenGL mitteilen. Dies übernimmt die Funktion glTexImage2D:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Parameter steht für den Typ der Textur. Die Dimension des Typs muss hier mit der des Befehls übereinstimmen (glTexImage2D erlaubt also nur GL_TEXTURE_2D). Der zweite Parameter gibt die Nummer des Level of Detail (LoD) an. Für den Anfang reicht hier der Level 0. Der dritte Parameter gibt an, wie viele Farbkomponenten in dem Bild enthalten sind (1-4). Die zwei folgenden Parameter übermitteln OpenGL die Breite und die Höhe des Bildes. Der sechste Parameter gibt die Breite des Rahmens an. Im siebenten Parameter wird das Format verlangt, in welcher Reihenfolge die einzelnen Farbkomponenten gespeichert sind. Bei Bitmaps ist das immer die Reihenfolge Blau, Grün, Rot. Der Typ, der einzelnen Farbwerte muss im 8. Parameter angegeben werden. Letztendlich müssen im 9. Parameter nur noch die Bildpunkte selbst übergeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit Hilfe dieser Funktion sollten nur Texturen der Größe 2^n x 2^n erzeugt werden. Andernfalls werdet Ihr die Textur nicht in Ihrer vollen Schönheit, d.h. überhaupt nicht betrachten können. Es gibt jedoch Möglichkeiten Texturen zu laden, die nicht die Größe 2^n entsprechen. Die Funktion [[gluBuild2DMipmaps]] bildet hier beispielsweise eine Alternative.&amp;lt;br&amp;gt;&lt;br /&gt;
Das war es auch schon. Wer mehr über die einzelnen Parameter und Befehle wissen will ist herzlich eingeladen in unserem Wiki umherzustöbern und sein Wissen zu erweitern um später selbst vielleicht einmal ein paar Artikel im Wiki zu veröffentlichen.&lt;br /&gt;
&lt;br /&gt;
Die Daten im Arbeitsspeicher brauchen wir nun nicht mehr. Bei SDL geben wir sie so frei:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;SDL_FreeSurface(tex);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fassen wir das ganze bei SDL nochmal zusammen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;var&lt;br /&gt;
  tex : PSDL_Surface;&lt;br /&gt;
begin&lt;br /&gt;
  tex := IMG_Load('./wiki.jpg');&lt;br /&gt;
  if assigned(tex) then&lt;br /&gt;
  begin		&lt;br /&gt;
    glGenTextures(1, @texture);&lt;br /&gt;
    glBindTexture(GL_TEXTURE_2D, texture);&lt;br /&gt;
		&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&lt;br /&gt;
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;
		&lt;br /&gt;
    // Achtung! Einige Bildformate erwarten statt GL_RGB, GL_BGR. Diese Konstante fehlt in den Standard-Headern&lt;br /&gt;
    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels);&lt;br /&gt;
&lt;br /&gt;
    SDL_FreeSurface(tex);&lt;br /&gt;
  end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kommt aber bitte nicht auf die Idee die Textur in euerer Hauptschleife wieder und wieder neu zu laden. Es reicht die Textur einmal zu laden und von da an steht sie einem solange zur Verfügung bis man gedenkt sie wieder aus dem Grafikkartenspeicher zu entfernen.&amp;lt;br&amp;gt;&lt;br /&gt;
Das übernimmt die Funktion [[glDeleteTextures]]. glDeleteTextures funktioniert ähnlich wie [[glGenTextures]], nur dass die Texturen entfernt werden. Der erste Parameter gibt die Anzahl der zu löschenden Texturen an, während der zweite Parameter den Namen der Textur bzw. ein Array der Namen mehrerer Texturen verlangt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das ist doch für den Anfang nicht schlecht. Ihr solltet nun in der Lage sein, zumindest einfache Objekte zu texturieren. Das ist eigentlich das gesamte Grundprinzip. Natürlich gestaltet es sich schwieriger, ein komplexeres Objekt mit UV-Koordinaten zu versehen, als ein Quad, aber an der Technik selbst ändert sich nur wenig. Wir werden nun einige Spielereien zeigen, die man mit Texturen machen kann, damit Ihr ein Gefühl dafür bekommt, wie man ein Problem elegant umschiffen kann!&lt;br /&gt;
&lt;br /&gt;
==Die Rückkehr der Matrizen==&lt;br /&gt;
===Texturen===&lt;br /&gt;
Tja... und da ich ein Sadist bin [Anm. des Lektors: Ooooh ja!] werden wir uns nun nochmals den Matrizen zuwenden! Dachtet Ihr etwa, Ihr seid die Dinger schon wieder los? Ich habe Euch im letzten Tutorial angedroht, dass es nicht nur eine Matrix für die &amp;quot;Welt&amp;quot; gibt, sondern auch noch weitere. Unter anderem eben auch für Texturen.&lt;br /&gt;
&lt;br /&gt;
Die Texturmatrix funktioniert streng genommen genauso wie auch die Worldmatrix. Solange wir sie aktiv haben, wird sie von jedem Matrixbefehl berücksichtigt! Einziger wirklicher Unterschied ist, dass sie nicht die Position oder die Form eines Objektes beeinflusst, sondern nur das Rendern der Textur selbst. Hö? Was meint der Kerl bloß damit?! Nun... stellt Euch vor, Ihr habt ein Quad und wollt darauf eine Textur bewegen, so dass es aussieht, als würde sie sich von rechts nach links bewegen! Was wir jedoch nicht wollen ist, dass sich das Objekt bewegt, sondern nur, das was darauf zu sehen ist. Stellt Euch vor, Ihr schaut aus einem Fenster und seht einen wolkigen Himmel, der Wind bläst die Wolken von einer Himmelsrichtung zur anderen. Ihr könntet so z.B. das Fenster als Quad nehmen und dann die Textur darauf zeichnen und glaubt mir, die Illusion würde auffliegen, sobald sich das Fenster mit der Textur bewegen soll. Nein, stattdessen bewegen wir nur die Textur auf dem Quad und zwar ohne das UV-Mapping anzutasten. Wir beeinflussen einfach die Art, wie die Textur auf das Quad projiziert werden soll. Dafür dient die Texturmatrix.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns mal vor, dass wir unser Quad zeichnen und eine Variable X haben, die wir bei jedem Rendervorgang leicht erhöhen. Dies soll die Bewegung darstellen. Alles was wir nun tun müssen ist, die Texturmatrix entsprechend anzupassen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;glMatrixMode(GL_TEXTURE);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  glTranslatef(x,0,0);&lt;br /&gt;
glMatrixMode(GL_MODELVIEW);&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist bereits der ganze Spuk! Wir teilen OpenGL durch glMatrixMode mit, dass sich ab sofort alle Veränderungen der Matrix nur noch auf die Texturmatrix beziehen sollen. Danach setzen wir diese sofort auf ihren Standardwert zurück. Der Grund hierfür sollte Euch von der Worldmatrix noch in Erinnerung sein. Anschließend ändern wir die Position der Textur auf dem Quad. Würden wir X jedes Mal um 1 Einheit erhöhen, so würde diese Operation ohne Effekt bleiben, da wir die Textur immer um ihre ganze Größe nach links projizieren würden. Würden wir X z.B. bei jedem Vorgang um 0.01 erhöhen, so würde die Textur sich langsam von rechts nach links bewegen. Ich denke, Ihr könnt bereits erahnen, welche Parameter dafür verwendet werden, um eine Textur von unten nach oben zu bewegen ;).&lt;br /&gt;
&lt;br /&gt;
Wichtig ist auf jeden Fall, dass Ihr anschließend mit glMatrixMode wieder die Worldmatrix aktiviert, da sonst alle weiteren Matrixmanipulationen auf die Texturmatrix angewandt werden würden. Denkt nicht, dass die Texturmatrix damit deaktiviert wird! Ab sofort wird auf das Objekt sowohl die World- als auch die Texturmatrix angewendet. Seht Ihr? Das Ganze ist doch gar nicht ganz so schlimm. Es versteht sich auch von selbst, dass Ihr glRotate und glScale ebenfalls darauf anwenden könnt, natürlich auch nach den gleichen Regeln auf die Worldmatrix. Experimentiert am Besten auch etwas mit diesen Einstellungen herum!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wir tapezieren unsere Welt mal anders==&lt;br /&gt;
===Am Fließband===&lt;br /&gt;
Eigentlich sollte an dieser Stelle bereits Schluss sein. Ich wurde allerdings während des Schreibens des Tutorials nach einer Sache gefragt und möchte die Chance nutzen, diese Frage zu beantworten und gleichzeitig das angewandte Wissen der vorhergehenden Lektion etwas zu vertiefen. &lt;br /&gt;
&lt;br /&gt;
Wir haben folgende Problematik: Wir brauchen eine animierte Textur auf einem Objekt. Dies könnte z.B. eine bewegte Lavamasse sein oder irgendwas Glibbriges, was am Boden wabbelt. Oder eben in unserem Fall eine Folge von Zahlen, die wie ein Countdown aufgelistet werden. Sicherlich könnte nun jemand von Euch auf die Idee kommen, viele einzelne Texturen zu laden und diese in einem Array zu speichern. Dies mag auch durchaus sinnvoll sein nicht jedoch, wenn es sich um kleine Bilder handelt (bei uns z.B. 32x32 Pixel).&lt;br /&gt;
&lt;br /&gt;
Auch bei Bitmap-Fonts würde man nie auf die Idee kommen, für jeden Buchstaben eine einzelne Textur zu verwenden, sondern vielmehr eine Textur mit allen Buchstaben darauf erstellen, da dies u.a. den Ladevorgang erheblich beschleunigt! Klingt einleuchtend oder? Aber wie sollen wir dem Programm mitteilen, welcher Teil der Textur auf welche &amp;quot;Ecke&amp;quot; geklebt werden soll? Nun... auch hierbei heißt des Lösungs Rätsel [Anm. des Lektors: Er macht's schon wieder. Herrlich...] UV-Mapping!&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers.gif]]&lt;br /&gt;
&lt;br /&gt;
Dies ist unsere Textur! Sie hat eine Gesamtlänge von 256x32 Bildpunkten und wie man leicht sehen kann, soll sie aus 8 Teilstücken bestehen. Die V-Koordinate können wir in diesem Fall getrost vernachlässigen, weil sie in diesem Fall immer konstant sein wird, weil wir die ganze Höhe der Textur verwenden wollen. Sie wäre nur dann interessant, wenn wir z.B. noch eine zweite Reihe darunter setzen würden. Ich denke jedoch, dass jemand der das gleich folgende verstanden hat, sofort eine Lösung für diese &amp;quot;Problematik&amp;quot; finden wird ;).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_numbers2.gif]]&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, dass wir uns bewusst werden, dass eine Textur beim UV-Mapping immer von 0 bis 1 reicht. Um nun die einzelnen Bilder aus einer Textur auf ein Objekt zu setzen, müssen wir nichts anderes machen, als zu errechnen, an welcher Stelle ein Bild anfängt und wo es aufhört. Nur zur Kontrolle, damit es auch jeder begreift: Würden wir nur die erste Hälfte der Textur auf ein Objekt kleben, so müsste unsere U-Koordinate von 0 bis 0.5 reichen. Die zweite Hälfte hingegen von 0.5 - 1.0. Soweit klingt es doch noch alles logisch oder?&lt;br /&gt;
&lt;br /&gt;
Genauso müssen wir auch vorgehen, wenn wir einzelne Bilder auf einem Quad abbilden wollen. In unserem Fall müsste die U-Koordinate von 0 bis 1/8 reichen. Das zweite Bildchen hingegen von 1/8 bis 2/8 etc. D.h. wir wissen, dass jedes unserer Bilder 1/8 &amp;quot;Einheiten&amp;quot; lang ist! Und somit haben wir ja bereits eine Lösung für unser Problem. Um das ganze dynamisch auszudrücken: Wir brauchen nur die Größe der Textur durch die Anzahl der Bilder zu teilen. Bevor jemand einen Denkfehler macht: Es ist hierbei ganz egal, wie groß die Textur wirklich ist (hier 256x32 Pixel). Dank OpenGL errechnen wir das UV-Mapping ja in absoluten Größen.&lt;br /&gt;
Nun der Code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;PicLength:= 1 / PicCount;&lt;br /&gt;
PicPos:=Round(Pic)*PicLength;&lt;br /&gt;
glBegin(GL_QUADS);&lt;br /&gt;
  glTexCoord2f(PicPos,		    1); glVertex3f(-1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 1); glVertex3f(1,1,0);&lt;br /&gt;
  glTexCoord2f(PicPos + PicLength, 0); glVertex3f(1,-1,0);&lt;br /&gt;
  glTexCoord2f(PicPos,		    0); glVertex3f(-1,-1,0);&lt;br /&gt;
glEnd;&lt;br /&gt;
&lt;br /&gt;
Pic:=Pic + MovementValue;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pic ist in diesem Fall eine Variable vom Typ Single, die langsam erhöht wird. Wir runden den Wert hier, so dass beim Erreichen eines jeden ganzzahligen Wertes das nächste Bild angezeigt wird. Wir multiplizieren die Nummer des anzuzeigenden Bildes mit der Breite eines Bildes, um die Anfangsposition zu erhalten und addieren dann noch eine volle Bildbreite dazu, um die Endposition zu erhalten. Hört sich gewaltig gefährlich an, liegt aber mehr an meinem mangelnden Ausdruck als an der Schwierigkeit dieses Problems ;).&lt;br /&gt;
&lt;br /&gt;
Im Sample werdet Ihr noch sehen, was passiert, wenn man den Wert nicht rundet. Man erhält in diesem Fall einen &amp;quot;flüssigen&amp;quot; Bildübergang. Letztendlich gibt es viele Möglichkeiten, solche Ideen zu implementieren. Nehmt dies einfach als kleineren Gedankenschub und vor allem: Werdet Euch bewusst, was genau dort passiert! Eine Menge toller Dinge lassen sich mit einem guten UV-Mapping erzielen.&lt;br /&gt;
Wer noch etwas umherexperimentieren will kann gern versuchen selbes Ziel mit Hilfe der Texturenmatrix zu erreichen. Die Lösung ist verblüffend einfach.&lt;br /&gt;
&lt;br /&gt;
===Terraforming mal anders===&lt;br /&gt;
Relativ lange habe ich nach einem guten Beispiel für folgende Problematik gesucht: Ich wollte Euch die UV-Koordinaten etwas näher bringen und Euch zeigen, wofür man sie einsetzen kann. Irgendwie wollte mir nichts Interessantes aus meinem Kopf entspringen bis ich irgendwann in einigen alten Programmen von mir rumgewühlt habe und einen alten Terrainrenderer von mir fand. Schon war die Idee da! Wir schreiben ein kleines Programm, das eine ganz simple, unoptimierte Landschaft rendern wird. Das hört sich sicherlich Anfangs relativ gewaltig an, mit etwas Verständnis für die oberen Probleme sollte dies jedoch kein Problem für Euch sein.&lt;br /&gt;
&lt;br /&gt;
Zuvor allerdings ein paar Gedankenspiele. Zunächst widmen wir uns kurz der Texturiering. Wie würde die simpelste Landschaft aussehen, die wir uns vorstellen können? Richtig! Sie wäre ein einfaches, flach liegendes Quadrat mit einer Textur überzogen, der Wand aus unserem ersten Versuch sehr ähnlich! Dies hat jedoch einen klitzekleinen Nachteil: Wir könnten keine Höhenstufen einbauen und ohne die wäre die Landschaft nur halb so realistisch. Denn wir wollen versuchen, folgende Szene zu zaubern:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscape.gif|thumb|256px|none|eine Lanschaft]]&lt;br /&gt;
Um allerdings Höhen einzubinden, müssen wir die Landschaft in viele kleinen Quads unterteilen, die natürlich an Ihren Eckpunkten unterschiedliche Höhen haben, sich jedoch jeweils einige Punkte teilen. Es versteht sich von selbst, dass diese die gleiche Höhe haben müssen, damit die Landschaft auch durchgängig ist und nicht irgendwelche mysteriösen Löcher darauf erscheinen ;).&lt;br /&gt;
Auf folgendem Screenshot kann man dies deutlich erkennen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landwire.gif|thumb|256px|left|Gitter Ansicht der Landschaft]]&lt;br /&gt;
Technisch gesehen ist das Ganze einfach zu realisieren, da wir nur begreifen müssen, dass alle Quads nebeneinander liegen und sich - bis auf die äußeren alle einen Eckpunkt teilen. Nun müssen wir beim Rendern jeden Eckpunkt nur noch vom angrenzenden Quad lesen und fertig ist die Landschaft. Ich will da nicht näher drauf eingehen, weil es sich hier nicht um ein Tutorial zur Landschaftsgestaltung handelt. Der Code sollte sich eigentlich von selbst erklären.&lt;br /&gt;
&lt;br /&gt;
Vielmehr sollten wir uns einer anderen Problematik widmen! Nämlich wie zur Hölle texturieren wir die Landschaft so, dass sie nicht zur Marke &amp;quot;augenfeindlich&amp;quot; gehört?&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tutimg_lektion4_landscapeerror.gif|thumb|256px|right|wiederkehrende Landschaft]]&lt;br /&gt;
Wenn Euer erster Gedanke dabei &amp;quot;Boah, cool!&amp;quot; ist, dann gibt's eins auf die Finger! Das wollen wir doch nicht... wie sieht den die Landschaft aus. Eine immer wiederkehrende Landschaft -&amp;gt; man erkennt sofort, dass wir hierbei auf jedes Quad die gleiche Textur geklebt haben. Doch wie schaffen wir es nun, dass wir eine Textur über alle Quads ziehen, so dass die ganze Landschaft mit einer Textur überzogen ist anstatt nur über ein einzelnes Feld?&lt;br /&gt;
Nun, des Lösungs Geheimnis [Anm. des Lektors: Ich liebe ihn dafür! Andere lösen Rätsel. Er geheimnist Lösungen] sind eben unsere UV-Koordinaten und einige pfiffige Köpfe unter Euch sollten bereits einen ersten Verdacht haben. Denn die erste Idee sollte es sein, den linken unteren Punkt eine UV-Koordinate von (0/0) zu geben und der rechten oberen (1/1).&lt;br /&gt;
Alles was wir nun also machen müssen, ist, uns die entsprechenden UV-Koordinaten für die Quads dazwischen auszurechnen und sie dann den Punkten zuzuweisen. Dafür benötigen wir zunächst die Breite eines Quads. Mit normaler Logik lässt sich folgende Aussage aufstellen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;qw:=1 / XCount&lt;br /&gt;
qh:=1 / YCount;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Ein Quad benötigt die Länge von 1 durch die Anzahl der Quads in einer Reihe oder Spalte. Genauso verhält es sich auch mit der Höhe. Nun brauchen wir beim Rendern nur noch dem jeweiligen Quad in einer For-Schleife die entsprechende Koordinate zuzuweisen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;U:=1 / XCount;&lt;br /&gt;
V:=1 / YCount;&lt;br /&gt;
&lt;br /&gt;
for y:=0 to YCount-1 do&lt;br /&gt;
begin&lt;br /&gt;
  glPushMatrix;&lt;br /&gt;
  for x:=0 to XCount-1 do&lt;br /&gt;
  begin&lt;br /&gt;
    glBegin(GL_QUADS);&lt;br /&gt;
      glTexCoord2f(U*x,     V*(y+1)); &lt;br /&gt;
      glVertex3f(0,  Map[x,y+1],  0);&lt;br /&gt;
      glTexCoord2f(U*x,     V*y);     &lt;br /&gt;
      glVertex3f(0,  Map[x,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*y);     &lt;br /&gt;
      glVertex3f(1,  Map[x+1,y],  1);&lt;br /&gt;
      glTexCoord2f(U*(x+1), V*(y+1));  &lt;br /&gt;
      glVertex3f(1, Map[x+1,y+1],  0);&lt;br /&gt;
    glEnd;&lt;br /&gt;
    glTranslatef(1,0,0);&lt;br /&gt;
  end;&lt;br /&gt;
  glPopMatrix;&lt;br /&gt;
  glTranslatef(0,0,-1);&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Das sieht nach einem herben Stück Arbeit aus oder? Aber wenn Ihr Euch das ganze mal aufzeichnet und im Kopf durchspielt, wird der Groschen fallen. Denkt mal etwas darüber nach! Wenn es dann doch noch Probleme mit dem Verständnis geben sollte, wird das nächste Kapitel hoffentlich jedes Missverständnis aus dem Wege räumen ;).&lt;br /&gt;
&lt;br /&gt;
==Nachwort==&lt;br /&gt;
Okay... ich hoffe Ihr fühlt Euch nach der Abarbeitung dieses Tutorials genauso wie ich, nachdem ich es für Euch geschrieben habe... nämlich elend. Irgendwie wurde das immer mehr und ich sagte mir immer wieder &amp;quot;nein, dass ist nicht genug. Das muss genauer und anschaulicher werden&amp;quot;. Dies ist auch der Grund dafür, warum dieses eines der größten Tutorials mit den meisten Bildern usw geworden ist. Erst sollte es noch etwas mehr werden und dann in mehrere Tutorials aufgespaltet werden, allerdings glaube ich mit diesem Tutorial einen guten Mittelweg zwischen Information und Totlabern gefunden zu haben. Lasst es mich wissen, wie Ihr dazu steht!&amp;lt;br&amp;gt;&lt;br /&gt;
Und bevor die Kritiker gleich wieder alle aus Ihren Löchern kommen und mir sagen, dass einige Bereich einfach als gegeben angenommen werden; denen sei nur gesagt, dass wir u.a. auch versuchen Rücksicht auf Leute zu nehmen, die noch nie 3D programmiert haben und vielleicht Eurem Wissen nicht standhalten können. Daher halte ich es hier für wichtiger, Grundlagen wie UV-Koordinaten und den Einsatz von Texturen zu erklären, als ihnen tausende von Zeilen um die Ohren zu hauen, wie sie die Bytes von der Festplatte in den Arbeitsspeicher laden können. Um jedoch keine Wissenslöcher offen zu lassen: Ihr könnt Euch sicher sein, dass spezielle Tutorials folgen werden, die sich speziell mit dem Laden verschiedener Formate beschäftigen und die genaue Interna (was im Hintergrund abläuft) zu erklären versuchen. Auch das Alpha Blending wird hier mehr zu &amp;quot;Show-Zwecken&amp;quot; verwendet und wird zusammen mit dem Z-Buffer genauer erklärt werden! &amp;lt;br&amp;gt;&lt;br /&gt;
Also bloß keine falsche Hektik! Ich weiß ... einige von Euch sind recht ungeduldig, aber ständiges Nachfragen und Drängeln führt zu nichts. Versucht Fragen lieber ins Forum zu setzen, damit dort ein wenig Leben reinkommt. Denn wenn es dort belebter wird, kommen auch schneller neue Leute und vielleicht sind ja auch welche dabei, die dann das DGL-Team entlasten können. Also nutzt bitte das Forum, anstatt andauernd per ICQ oder Mail irgendwelche Fragen zu stellen! Die Antwort wird auch nicht viel länger auf sich warten lassen. Im Forum jedoch ist alles dokumentiert und auch anderen zugänglich, so dass ich nicht die gleiche Frage bis zu 5 mal am Tag beantworten muss. Sorry aber das geht einem auf die Nerven und vor allem auf die Zeit ;). Schließlich sind wir keine Maschinen sondern Menschen, die auch ein privates Leben haben ^__-.&lt;br /&gt;
&lt;br /&gt;
Glaubt uns, wir investieren einen sehr großen Teil unserer Zeit in dieses Projekt und solch ein Tutorial lässt sich nicht binnen weniger Tage anfertigen. Jeder der so etwas bereits einmal gemacht hat, wird wissen was ich meine. Es muss ein Konzept her, es müssen Samples geschrieben, Screenshots gemacht werden und ein halbwegs verständlicher Text her. Und nichtsdestotrotz soll es am Ende auch noch passen, einem möglichst großen Publikum Wissen vermitteln, am Besten von Schreib- und Sprachfehlern befreit und in einem halbwegs ansehnlichen HTML-Dokument präsentiert werden. Ein langer Weg ;).&lt;br /&gt;
Okay, in diesem Sinne, bis bald ;)!&lt;br /&gt;
btw: Vielen Dank an Magellan für die Bereitstellung und Integration seiner &amp;quot;besonderen Lernleistung&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Euer&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|[[Tutorial_lektion3]]|[[Tutorial_lektion5]]}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorial|Lektion4]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Postmortem_Asteroids&amp;diff=13212</id>
		<title>Postmortem Asteroids</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Postmortem_Asteroids&amp;diff=13212"/>
				<updated>2005-09-21T17:03:44Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Postmortem: Asteroids =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Herzlich willkommen zu diesem Postmortem zu der Entwicklung von Asteroids. In folgendem Artikel möchte ich genauer darauf eingehen, mit welcher Einstellung ich an das Projekt heran gegangen bin, wo ich auf Probleme gestoßen bin, bzw. was einwandfrei funktioniert hat. Letzten Endes möchte ich noch darauf eingehen, was ich aus diesem Projekt gelernt habe, und was ich beim nächsten Mal anders machen würde. &lt;br /&gt;
== Die ersten Schritte oder der Urschleim ==&lt;br /&gt;
Wie wohl die meisten Programmierer träumte und träume ich auch heute noch, von dem eigenen DOOM3. In meinem jugendlichen Übermut begann ich also einen kleinen 3D-Weltraumshooter zu schreiben. Soweit lief alles wunderbar. Irgendwann sah ich mich jedoch mit dem Problem konfrontiert, dass man weder gegen eine halbwegs intelligente KI, noch im Netzwerkmodus gegen andere Spieler antreten konnte. Was hilft einem also ein Shooter mit tollster Grafik, wenn man keine Gegner hat? Nun ja! Ich will nicht übertreiben. Auch grafisch war das Spiel kein Hammer, denn ich bin kein Künstler und so fehlte es mir an guten Modellen und Texturen. So entschied ich mich, das Projekt vorerst einzufrieren. Ich kam zu dem Entschluss, ein Spiel zu schreiben, bei dem sowohl die Künstliche Intelligenz als auch ein Netzwerkmodus einfacher zu realisieren sind. Außerdem sollte sich der Bedarf an Modellen und Grafiken in Grenzen halten. Daher kam es zu dem radikalen Umschwung von 3D auf 2D. Die Wahl fiel auf Asteroids, weil ich hier auch einige Codeschnipsel aus dem Shooter verwenden konnte.&lt;br /&gt;
== Die Erkenntnis ==&lt;br /&gt;
Die Grundeinstellung, mit der ich an das Projekt heran ging, lässt sich ganz einfach beschreiben: Schreibe ein Spiel, welches spielbar ist und in absehbarer Zeit fertig wird. Aus diesem Grund erstellte ich eine genaue Projektplanung. Zuerst wollte ich mich auf das Spielerische konzentrieren. Und damit meine ich nicht etwa, welche Asteroidentypen oder verschiedenen Spielmodi es später im Spiel geben sollte, sondern das simple Herumfliegen, Schießen, Explodieren und Spawnen. An der Grafik könnte ich später immer noch feilen. Diese Einstellung hat sich bei mir bewährt, und sie ist es, mit der ich an jedes neue Projekt heran gehe.&lt;br /&gt;
&lt;br /&gt;
Gelernt, wie man ein solches Spiel am Besten aufbaut, habe ich aus dem Bomberman-Tutorial von Sascha Willems. Ich versuchte den Code so flexibel wie möglich aufzubauen. So wurde z.B. eine Grundklasse erstellt, von welcher ich alle anderen Klassen für z.B. Spieler oder Asteroiden ableiten konnte. Dies hat Änderungen jederzeit effizient möglich gemacht. Außerdem konnte ich auf diverse Manager zurückgreifen, die ich bereits vorher entworfen hatte. Dazu zählt u.a. ein Texturenmanager, Fontmanager, Modelmanager und ein Soundmanager.&lt;br /&gt;
&lt;br /&gt;
Auf diese Art und Weise verlief die Entwicklung sehr schnell und problemlos. Nach knapp 5 Tagen hatte ich bereits die erste spielbare Version fertig gestellt. Zwei weitere Tage habe ich benötigt, um mich um den Augenschmaus wie z.B. Licht- oder Partikeleffekte zu kümmern. Angetrieben durch den Feedback, denn ich aus dem Forum erhielt integrierte ich mehrere Spielmodi, die das Spiel interessanter und vielseitiger gestalten sollten.&lt;br /&gt;
== Das bissel Drumherum ==&lt;br /&gt;
Als ich begann mich um die Menüs zu kümmern musste ich schnell feststellen, dass Menüs wohl zu den Dingen gehören, die ich vom Aufwand her unterschätzt hatte. Ein Hauptmenü mit ein paar Buttons lässt sich noch relativ leicht realisieren. Da ich aber auch Dinge wie Tastaturbelegung und Bildschirmeinstellungen über die Menüs regelbar machen wollte, reichten Buttons allein nicht aus. Durch den Menümanager, der sich mit der Zeit entwickelte, konnten später Dinge wie eine Highscore oder ein einfaches Menü zum Ändern der Steuerung relativ einfach implementiert werden. Alles in allem hat die Entwicklung der Menüs und selbstverständlicher Features wie die Änderung der Bildschirmeinstellungen weit mehr Zeit in Anspruch genommen, als die Entwicklung des Spiels selbst. Aber auch hier konnte ich mich nicht beklagen, denn die Entwicklung ging sichtlich voran. Dies kann unheimlich motivierend sein. Nichts ist demotivierender als an etwas zu basteln, ohne einen Fortschritt erkennen zu können. &lt;br /&gt;
== Am Rande der Verzweiflung ==&lt;br /&gt;
Das größte Problem war jedoch der Netzwerkmodus. Da ich mich mit diesem Thema bisher nicht weiter auseinander gesetzt hatte, versuchte ich mich mit den Indykomponenten. Das Problem, vor dem ich mich schnell stehen sah, war das der Synchronisation. Mit den Indykomponenten traten immer wieder Fehler auf, auf die ich keinen Rat wusste. Letzten Endes stieg ich völlig entnervt, dank dem Tipp von Sascha Willems, auf die Windows Sockets um. Diese erlaubten mir eine vereinfachte Fehlersuche und damit gelang letztendlich auch der Durchbruch. Trotzdem waren Wochen vergangen, bis ich einen halbwegs funktionierenden Netzwerkcode hatte, bei dem der Nutzer des ein Clients, das selbe Spiel spielte, wie der Nutzer eines anderen.&lt;br /&gt;
&lt;br /&gt;
Hinzu kam, dass ich den Code des Spieles ständig umstrukturieren musste, da ich ihn trotz allen Überlegungen viel zu unflexibel gestaltet hatte. Merke: Erst, wenn man bei all den eigenen Prozeduren und Funktionen den Überblick verliert, hat man einen wirklich flexiblen Code. Im Ernst! Man sollte den Code in so viele kleine Prozeduren und Funktionen unterteilen, wie möglich. Erst wenn der gesamte Spielablauf theoretisch über eine Konsole gesteuert werden kann, hat man ganze Arbeit geleistet.&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Ich hoffe, dass Ihr aus diesem Postmortem etwas gelernt habt, was euch bei künftigen Projekten hilfreich sein könnte. Weiterhin hoffe ich, Euch hiermit zu neuen Projekten angespornt zu haben. Nehmt Euch lieber erst einmal ein kleines Projekt vor, welches Ihr aber fertig stellen könnt. Mit all dem Wissen, welches Ihr dabei erwerbt, könnt Ihr Euch dann auch an ein größeres wagen. Außerdem habt Ihr mit dem kleinen Projekt zumeist bereits eine kleine Codebasis geschaffen, die in weiteren Projekten zum Einsatz kommen kann.&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Magellan'''&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Links ==&lt;br /&gt;
*[http://trinidad.delphigl.com Asteroids Projektseite]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=9439</id>
		<title>Tutorial Lektion 2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=9439"/>
				<updated>2005-08-23T17:55:21Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Entdeckung einer neuen Welt =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Ich möchte Euch an dieser Stelle bei DGL herzlich willkommen heißen. Vermutlich wird dies eines der ersten Tutorials sein, das Ihr als Einsteiger lesen werdet. Wahrscheinlich werdet Ihr dann auch noch nicht lange bei uns sein und Euch nicht vorstellen können, dass all die Schreiber auf unserer Seite keine Gurus, sondern ganz normale Menschen sind.&lt;br /&gt;
&lt;br /&gt;
Man kann uns also jeder Zeit im Forum anfassen, uns Fragen stellen, Vorschläge unterbreiten oder einfach nur einmal kurz mit einem Lob ermutigen weitere Texte zu verfassen ;-).&lt;br /&gt;
&lt;br /&gt;
Ich wünsche Euch an dieser Stelle viel Erfolg bei dem Einstieg in die Thematik OpenGL und ermahne Euch noch einmal, dass Ihr Eure Ziele nicht zu weit steckt. Wirklich Spaß beginnt OpenGL nämlich erst dann zu machen, wenn man stets kleinere Erfolge feiern kann.&lt;br /&gt;
== Höhere Mächte - Matrizen und ihre Folgen ==&lt;br /&gt;
=== Saubere Arbeit ===&lt;br /&gt;
Bevor wir direkt beginnen etwas zu Zeichnen müssen wir erst einmal das Bild löschen, denn wie in der vorherigen Lektion beschrieben zeichnen wir die Szene jeden Schleifendurchlauf neu. Das Löschen der Puffer, in dem die Bildinformationen enthalten sind übernimmt die Funktion [[glClear]]. Die Farbinformationen unser  [[Fragment|Fragmente]] (Fragmente sind vergleichbar mit den [[Pixel|Pixeln]] auf dem Bildschirm besitzen aber weitere Informationen wie z.B. Tiefenwerte. Bei der Ausgabe des Bildes werden diese Fragmente in Pixel umgewandelt) sind in dem so genannten [[Farbpuffer]] (Colorbuffer) gespeichert. Aus diesem Grund übergeben wir an die Funktion glClear die Konstante GL_COLOR_BUFFER_BIT.&lt;br /&gt;
&amp;lt;pascal&amp;gt;//Farbbuffer entleeren&lt;br /&gt;
glClear(GL_COLOR_BUFFER_BIT);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
[[bild:tutimg_lektion2_puffereffekt.gif|right]]&lt;br /&gt;
Mit Hilfe des Befehls [[glClearColor]] können wir festlegen, welche Farbinformationen mit dem Aufruf von glClear in den Colorbuffer geschrieben werden sollen. Wenn wir es also genau nehmen so löscht glClear den Colorbuffer nicht, sondern es schreibt ihn mit den definierten Werten voll. Standardmäßig erhalten die Fragmente eine schwarze Farbe.&lt;br /&gt;
&lt;br /&gt;
Es wird also nicht bei jedem Zeichenvorgang (Rendervorgang) der Bildspeicher gelöscht, sondern der Programmierer entscheidet, wann dies geschehen soll. Theoretisch könnt Ihr auch die Szene wiedergeben und dann löschen, bevor sie ausgegeben wird... wer's mag :).&lt;br /&gt;
&lt;br /&gt;
Wer sich entscheidet den Colorbuffer nicht zu löschen, der kann so auch einige nette Effekte erzeugen. Den Cheatern unter euch sollte der erreichte Effekt bekannt vorkommen, wenn man beispielsweise bei Counter-Strike durch die Wand gelaufen ist. Der Grund für das Verwischen ist in beiden Fällen derselbe: Das neue Bild wird gezeichnet, ohne dass das alte Bild aus dem Puffer entfernt wurde.&lt;br /&gt;
=== Und die Welt ist doch keine Scheibe ===&lt;br /&gt;
[[bild:tutimg_lektion2_koordinatensystem.jpg|256px|right]]&lt;br /&gt;
Nachdem wir nun wieder Ordnung im Speicher geschafft haben, können wir zum interessanten Teil kommen: &amp;quot;Wie darf man sich einen 3D-Raum vorstellen?&amp;quot; Nun  warum schaut Ihr Euch nicht einmal in Eurem Zimmer um?&lt;br /&gt;
&lt;br /&gt;
Versuchen wir doch mal, ein Beispiel direkt aus dem Leben gegriffen zu nehmen und stellen uns unsere Umgebung als Koordinaten-System vor (Igitt!). Der Monitor, der hoffentlich direkt vor uns steht, ist in diesem Fall unser Ursprung, d.h. er liegt an dem Punkt (0, 0, 0).&lt;br /&gt;
&lt;br /&gt;
Blicken wir seitwärts neben den Monitor, so sehen wir eine Linie (wenn Ihr es nicht tun solltest, macht Euch keine Sorgen  solche Anfälle hat der Autor häufiger *g*), die von links nach rechts verläuft. Es handelt sich hierbei um die X-Achse, die links vom Monitor im negativen Bereich verläuft, rechts davon in den positiven.&lt;br /&gt;
&lt;br /&gt;
Nun blicken wir einmal nach oben und einmal nach unten und schon erspähen wir die Y-Achse, die oberhalb des Monitors positiv verläuft, unterhalb negativ. Wunderbar! Wenn Ihr bereits in 2D gearbeitet habt, solltet Ihr an dieser Stelle ein dümmliches Grinsen auf Eurem Gesichte haben und das wohltuenden Gefühl, dass Euch das doch alles bereits irgendwie bekannt vorkommt. Doch zu unserem Entsetzen können wir uns ja auch noch von unserem Bildschirm wegbewegen oder auch dichter heran (alle Kurzsichtigen unter uns sollten das nicht so persönlich nehmen, auch Sie leben in einem 3D-Raum ^__-).&lt;br /&gt;
&lt;br /&gt;
Dieses Phänomen ist im 3D-Raum typisch, jedoch nicht unerklärlich, da wir uns auf der Z-Achse bewegen. Rollen wir mit dem Stuhl vom Monitor weg, so gelangen wir in den positiven Bereich der Z-Achse, bewegen wir uns drauf zu, gelangen wir in den negativen Bereich. Jeder, der bereits in D3D programmiert hat, sollte sich schleunigst einprägen, dass das ein großer Unterschied zwischen D3D und OpenGL ist. Das kann sonst zu einigen wirklich fiesen Fehlern führen, wenn man es nicht weiß *fg*.&lt;br /&gt;
&lt;br /&gt;
Soweit so gut! Klingt bisher hoffentlich immer noch nicht so kompliziert. Nur keine Sorge, das Niveau versuchen wir zu halten ;).&lt;br /&gt;
&lt;br /&gt;
Speziell wenn Ihr bereits 2D-Spiele programmiert habt, solltet Ihr Euch sehr schnell von folgenden Gedanken trennen: Die Koordinaten, die Ihr seht und angebt, entsprechen in der Regel nicht den Pixeln des Bildschirmes, sondern so genannten Weltkoordinaten. Eine Definition für diese Weltkoordinaten gibt es nicht, denn wie groß diese sind ist dem Programmierer überlassen. Ob Ihr euer Objekt eine Einheit vor Euch und 0,1 Einheit rechts von Euch oder aber 100 Einheiten vor euch und 10 Einheiten neben Euch positioniert ist egal. Die euch zur Verfügung stehende Welt ist grenzenlos ;). Ihr könnt Eure Szene theoretisch unendlich klein oder aber unendlich groß darstellen. Das einzige was euch wirklich daran hindert ist die Größe und Auflösung der Euch zur Verfügung stehenden Typen wie Integer oder Single ;). Der eigentliche Größeneindruck eines Objektes entsteht durch die Geschwindigkeit mit der sich der Betrachter und andere Objekte in der Welt bewegen.&lt;br /&gt;
&lt;br /&gt;
=== Der erste Kontakt ===&lt;br /&gt;
Um nun etwas mit OpenGL rendern zu können, müssen wir uns bewusst werden, was die Worldmatrix ist. In dieser Matrix wird festgehalten, wie und wo ein Objekt gezeichnet wird. Das hört sich vielleicht zunächst recht merkwürdig an, lässt sich aber leicht veranschaulichen.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns vor, die Worldmatrix zeigt auf einen Punkt, an dem ein Objekt gezeichnet werden soll (ganz übel wir werden später detaillierter darauf eingehen. Sollte es jemand also nach der folgenden Erläuterung nicht verstanden haben, kann er mich selbstverständlich persönlich per Mail zur &amp;quot;Rechenschaft&amp;quot; ziehen oder aber er wirft einen Blick in unser OpenGLWiki :)).&lt;br /&gt;
&lt;br /&gt;
Diesen Punkt setzen wir nun am Anfang in den Mittelpunkt unseres Koordinatensystems. Um oberes Beispiel aufzugreifen: Den Bildschirm. Dies geschieht mit dem Befehl [[glLoadIdentity]] und entspricht einem Reset der Worldmatrix. Theoretisch können wir nun an dieser Stelle etwas zeichnen. Dies würde allerdings dazu führen, dass das Objekt sehr groß oder gar nicht zu sehen ist, weil wir uns eben auch an diesen Stellen befinden. Gehen wir doch einmal 1,5 Einheiten nach links und 6 Einheiten nach hinten!&lt;br /&gt;
&lt;br /&gt;
Hierfür sollte man sich bewusst werden, dass wir in OpenGL praktisch an einem Stuhl gefesselt sind, d.h. wir können uns gar nicht bewegen. Das soll uns aber nicht davon abhalten. Wir brauchen ja nur die ganze Welt so zu bewegen, dass es für uns aussieht, als ob wir uns bewegen. Denn wenn sich alles außer uns nach links bewegt, haben wir den Eindruck, wir wären nach rechts gewandert, right?&lt;br /&gt;
&lt;br /&gt;
Nun aber zu der Bewegung unseres ersten Objektes:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5,0,0);&lt;br /&gt;
glTranslatef(0, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Dies hat bewirkt, dass sich unser Zeichenstift 1,5 Einheiten nach links (negativer Bereich der X-Achse) und anschließend 6Einheiten nach hinten bewegt hat. Ich habe diesen Fall absichtlich in zwei Schritten gefasst, um es zu verdeutlichen. Sicherlich wäre es einfacher, alles mit nur einem Aufruf von [[glTranslate|glTranslate*]] zu machen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Man beachte, dass in diesem Fall die 6 Schritte nach hinten notwendig sind um ein bisschen Distanz zum Objekt zu bekommen und nicht direkt in ihm zu stehen!&lt;br /&gt;
&lt;br /&gt;
Fertig! Schon haben wir dort unseren &amp;quot;Zeichenstift&amp;quot; positioniert, der nun auf weitere Zeichenkommandos von uns wartet. Das mag sicherlich alles ein wenig verwirrend klingen testet es am Besten aus und spielt mit den Parametern und erkennt, was gemeint ist :).&lt;br /&gt;
== Von Sichtungen... ==&lt;br /&gt;
=== Die Büchse der Pandora ===&lt;br /&gt;
Nun sind wir aber auch alle scharf darauf, endlich etwas zu rendern und auf dem Bildschirm auszugeben. Dies geschieht z.B. mit folgenden Zeilen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
  glVertex3f(-1,-1, 0);  &lt;br /&gt;
  glVertex3f( 1,-1, 0);&lt;br /&gt;
  glVertex3f( 0, 1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wir erkennen hierbei eindeutig eine Art Block. Gerade wir Pascaler sollten diese ja lieben :-&amp;gt;. Wir teilen OpenGL mit Hilfe von [[glBegin]] mit, dass wir ein Objekt zeichnen wollen. In diesem Fall übergeben wir den Parameter GL_TRIANGLE, der OpenGL angibt, dass folgende Punkte als ein Dreieck interpretiert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Anschließend folgt ein dreifacher Aufruf von [[glVertex|glVertex3f]]. Jeder Aufruf erzeugt nun einen Punkt (Vertex) in unserem 3D-Raum. Da wir OpenGL bei glBegin mitgeteilt haben, dass diese Punkte zu einem Dreieck zusammengefügt werden sollen wird das auch so getan ;).&lt;br /&gt;
&lt;br /&gt;
Wie wir auf dem Bild erkennen können, wurde unser Dreieck wie erwartet nach links verschoben abgebildet und auch mit einem leichten Abstand zur Kamera, nämlich 6 Einheiten entlang der Z-Achse.&lt;br /&gt;
=== Guter Stoff! ===&lt;br /&gt;
Nun ... ein wenig trostlos sieht unser Dreieck nun doch aus, oder? Ich habe übrigens damals bei D3D rund eine Woche benötigt, bis ich ein schwarzes Dreieck hatte. Wir haben immerhin schon ein weißes ... aber wir gehen nun einen Schritt weiter und werden das Dreieck schön bunt einfärben.&lt;br /&gt;
&lt;br /&gt;
Bevor nun irgendjemand anfängt und Pixel für Pixel den Bildschirm nach zu pinseln oder gar sein PaintShop bereits offen hat, um die ersten Texturen zu erstellen, sei gestoppt! Es gibt für einfache Einfärbungen in OpenGL eine bessere Methode. Wir definieren einfach für jeden Eckpunkt eine Farbe und OpenGL wird dann sogar eigenständig die Farbverläufe dafür erstellen. Jeder der D3D kennt, wird diese Vorgehensweise bekannt vorkommen und er wird beginnen verzweifelt nach dem FVF zu suchen, um es korrekt zu definieren... Wenn Ihr einen Vertex zeichnet, so rendert OpenGL diesen automatisch &amp;quot;weiß&amp;quot; (Ah huch! Deswegen ist unser Dreieck auch weiß???). Alles was wir nun machen müssen, ist OpenGL mitzuteilen, dass es eine andere Farbe einsetzen soll. Und zwar wird OpenGL diese Farbe für alle folgenden Eckpunkte nutzen, so lange bis von uns ein anderes Kommando kommt.&lt;br /&gt;
&lt;br /&gt;
Der mysteriöse Befehl, um den ich nun schon die ganze Zeit herumschwafle ist [[glColor|glColor*]]:&lt;br /&gt;
&amp;lt;pascal&amp;gt;// Alle folgenden Eckpunkte werden rot gefärbt&lt;br /&gt;
glColor3f(1,0,0);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wobei jeder Parameter einen Farbwert repräsentiert und zwar nach dem Muster RGB. Es wird ein Wert zwischen 1 und 0 erwartet, wobei eine Eins &amp;quot;volle Farbsättigung&amp;quot; bedeutet. Das heißt in unserem Fall haben wir als Farbe &amp;quot;rot&amp;quot; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Und weil wir schließlich die Welt ein wenig bunter machen und nicht nur das weiße Dreieck rot färben wollten, werden wir nach jedem Eckpunkt eine neue Farbe setzen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
  glColor3f(1, 0, 0); glVertex3f(-1,-1, 0);  &lt;br /&gt;
  glColor3f(0, 0, 1); glVertex3f( 1,-1, 0);&lt;br /&gt;
  glColor3f(0, 1, 0); glVertex3f( 0, 1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Und dies ist dann unser farbenfrohes Ergebnis. Beeindruckend, wenn man bedenkt, wie wenig Aufwand letztendlich dahinter steckt, oder?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_dreieck.gif]]&lt;br /&gt;
&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Wer meine Tutorials kennt weiß, dass zum Abschluß noch immer ein wenig Geblubber von mir kommt (man beachte diese entzückende Wortwahl von meiner einer hoffe, der Lektor findet es auch amüsant). (Anm. des Lektors: Und wie!) Schauen wir doch mal stolz auf das zurück, was wir heute erreicht haben! Wir haben OpenGL initialisiert, ein erstes Dreieck auf den Bildschirm gezaubert und dieses in den Farbtopf gesteckt! Das solltet Ihr als ein historisches Ereignis ansehen. Als ich damals mit D3D angefangen habe, brauchte ich, um es mir selbst zu erarbeiten, ca. eine Woche (Das ist jetzt der Moment, in dem Ihr Eure Hände heben solltest und ein lautes &amp;quot;Call me God&amp;quot; aus Euch herauskommen sollte, so dass zumindest Eure unmittelbaren Mitmenschen denken, dass Ihr einen Dachschaden habt!!! Das gehört einfach mit dazu ^__- )&lt;br /&gt;
&lt;br /&gt;
Wie immer solltet Ihr Euch nun hinsetzen und Euch ein wenig mit den Parametern vertraut machen. Speziell bei glTranslate* solltet Ihr ein wenig mit den Parametern experimentieren, damit Ihr seht, was es mit den Matrizen auf sich hat und wie diese funktionieren. Wenn Ihr dann auch denkt, dass Ihr damit vertraut seid, versucht ein wenig mit den einzelnen Vertexpositionen zu experimentieren und verändert diese. Wenn auch das klar ist, setzt Euch in die Ecke und warte sehnsüchtig auf mehr von uns :D! (Anm: die &amp;quot;Ecke&amp;quot; ist nicht die Kneipe nebenan ... :)&lt;br /&gt;
&lt;br /&gt;
Im nächsten Kapitel werden wir dann Matrizen-Hardcore machen ... legt also schon mal Euer Aspirin parat, es wird witzig werden *grunz* :).&lt;br /&gt;
&lt;br /&gt;
Und wie immer freuen wir uns sehr über Feedback. Schreibt uns doch einfach ein paar Worte in unser [http://www.delphigl.com/forum/viewforum.php?f=8 Feedback-Forum]. Sagt was Ihr gut und was hingegen Ihr als schlecht empfunden habt! Auch freuen wir uns immer über Ideen für weitere Tutorials, teilt uns also bitte Eure Ideen mit ;)!&lt;br /&gt;
&lt;br /&gt;
Okay ich wünsche Euch einen angenehmen Tag / Nacht!&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION | [[Tutorial_lektion1]] | [[Tutorial_lektion3]]}}&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial&amp;diff=9101</id>
		<title>Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial&amp;diff=9101"/>
				<updated>2005-08-22T05:20:31Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* Einsteiger Tutorials */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Nochfolgend finden Sie eine Übersicht über all die Tutorials die bereits ins Wiki übertragen wurden.&amp;lt;br&amp;gt; &lt;br /&gt;
Alle Artikel sind auch weiterhin unter [http://www.delphigl.com/launcher.php?em=tutorials DelphiGL.com-&amp;gt;Tutorials] erreichbar.&lt;br /&gt;
&lt;br /&gt;
== Einsteiger Tutorials ==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable}}&lt;br /&gt;
!Link&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
![[Tutorial quickstart]]&lt;br /&gt;
|[[Bild:Tutorial_na.jpg|right]] &amp;quot;Quickstart: OpenGL &amp;amp; Delphi&amp;quot;.&amp;lt;br&amp;gt; &lt;br /&gt;
Für alle die einen schnellen Einstieg in die OpenGL Programmierung mit Delphi suchen hat Flash hier einen Einstieg geschaffen. Neben dem erstellen eines eigenen OpenGL-Templates hat er für alle die großes mit OpenGL vorhaben, am Ende noch einige Hinweise bereitgestellt.&lt;br /&gt;
|-&lt;br /&gt;
![[Tutorial lektion1]]&lt;br /&gt;
|[[Bild:Tutorial_na.jpg|right]] &amp;quot;Nicht zu weit aus dem Fenster lehnen&amp;quot;.&amp;lt;br&amp;gt; &lt;br /&gt;
Dieses Tutorial ist für alle Neueinsteiger gedacht. Hier werden Grundlagen von &amp;quot;Was ist OpenGL&amp;quot; bis zu &amp;quot;wie initialisiere ich OpenGL&amp;quot; besprochen.&lt;br /&gt;
|-&lt;br /&gt;
![[Tutorial lektion2]]&lt;br /&gt;
|[[Bild:Tutorial_na.jpg|right]] &amp;quot;Entdeckung einer neuen Welt&amp;quot;.&amp;lt;br&amp;gt; &lt;br /&gt;
Unter dieser Überschrift empängt euch Phobeus zu eurem ersten OpenGL Tutorial welches sich mit der Anwendung der OpenGL-API befasst.&lt;br /&gt;
|-&lt;br /&gt;
![[Tutorial lektion3]]&lt;br /&gt;
|[[Bild:Tutorial_na.jpg|right]] &amp;quot;Eine Welt des Grauens&amp;quot;?&amp;lt;br&amp;gt; &lt;br /&gt;
Hinter diesem Titel verbirgt sich ein Einsteigertutorial zum Thema Matrizen in OpenGL. Wiederum führt euch Phobeus durch den Stoff.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Shader ==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|{{Prettytable}}&lt;br /&gt;
!Link&lt;br /&gt;
!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
![[Tutorial_glsl]]&lt;br /&gt;
|[[Bild:Tutorial_glsl1.png|right]] &amp;quot;Einführung in GLSL&amp;quot;.&amp;lt;br&amp;gt; &lt;br /&gt;
Nach langem Ringen und Handeln hat es das ARB letztendlich doch geschaft eine einheitliche Shaderhochsprache für OpenGL zu veröffentlichen, nämlich glSlang. Mit glSlang können nun auch unter OpenGL Vertex- und Fragmentshader in einer lesbaren, C-ähnlichen Hochsprache geschrieben werden, was deren Entwicklung stark vereinfacht. Diese Einführung von Sascha Willems ist weniger ein Tutorial als ein kompletter Überblick über glSlang. Hier erfährt der Leser nicht nur wie man die Shader im Programm nutzt, sondern auch alles über die Sprachelemente, inklusive diverser Beispiele.&lt;br /&gt;
|-&lt;br /&gt;
![[Tutorial_glsl2]]&lt;br /&gt;
|[[Bild:Tutorial_na.jpg|right]] &amp;quot;GLSL Ergänzungen und Beispiele&amp;quot;.&amp;lt;br&amp;gt; &lt;br /&gt;
Dieses Tutorial von La_Boda ist eine direkte Fortsetzung des GLSL Tutorials. Es behandelt verstärkt die Praxis und liefert anhand von einigen Beispielen eine bessere Sicht auf die bereits gelernte Theorie.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_1&amp;diff=9093</id>
		<title>Tutorial Lektion 1</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_1&amp;diff=9093"/>
				<updated>2005-08-22T05:14:43Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Nicht zu weit aus dem Fenster lehnen =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Hallo,&lt;br /&gt;
in dem folgenden Tutorial möchte ich Euch etwas näher mit OpenGL vertraut machen. Der Großteil dieses Tutorials besteht aus bloßer Theorie, die jedoch absolut notwendig ist. Es ist nicht leicht über ein so trockenes Thema zu schreiben, denn in aller Regel sind Eure Erwartungen groß und wenn es schon keine aufwendige Grafikdemo wird, so wollt Ihr doch wenigstens ein Dreieck am Ende auf den Bildschirm gezaubert sehen. Seit nicht frustriert, wenn ich Euch nun verrate, dass das eigentliche Zeichnen (Rendern) erst im zweiten Tutorial behandelt wird. Ein leeres Fenster ist doch auch nicht zu unterschätzen oder ;)?&lt;br /&gt;
== Was ist (die) OpenGL? ==&lt;br /&gt;
Womit wir schon bei der ersten Frage wären. Ist es der, die oder das OpenGL. Um diese Frage zu beantworten müssen wir wissen, dass OpenGL ein Akronym für Open Graphics Library ist. Der englischen Begriff Library bedeutet Bibliothek womit wir auf die OpenGL schließen. Häufig findet OpenGL aber auch ganz ohne Pronomen Verwendung. Nachdem wir diese Sache klargestellt haben kommen wir zur eigentlichen Frage zurück. Was ist OpenGL?&lt;br /&gt;
&lt;br /&gt;
OpenGL ist eine API, die es uns erlaubt relativ einfach Grafiken auf dem Bildschirm auszugeben ohne jedoch zu wissen, was im Hintergrund genau geschieht. Das ganze ist in gewisser Weise mit der Windows-API vergleichbar. Wir wissen zwar, wie man ein Fenster erzeugt, was im Hintergrund jedoch genau geschieht wissen wir nicht. &lt;br /&gt;
&lt;br /&gt;
Weiterhin ist OpenGL plattformunabhängig. Theoretisch könntet Ihr OpenGL also unter jedem Betriebssystem nutzen und Eure Programme würden auch auf jeder Hardware laufen. Dies bringt jedoch den Nachteil mit sich, dass bestimmte Dinge wie die Fensterverwaltung, Tastatur- oder Maussteuerung aus der Bibliothek ausgeschlossen sind, da diese sich von Betriebssystem zu Betriebssystem unterscheiden können. Um diese Dinge müssen wir uns also selbst kümmern. Zum Glück bietet uns die VCL (Visual Component Library) von Delphi ein mächtiges Werkzeug um solchen Herausforderungen entgegenzutreten.&lt;br /&gt;
&lt;br /&gt;
OpenGL selbst besitzt nur einen relativ kleinen Sprachumfang. Die wenigen Funktionen, die jedoch vielseitig einsetzbar sind lassen sich sehr leicht erlernen. Die folge hiervon ist aber auch, dass es keine Funktion zum Zeichnen komplexer Objekte wie z.B. die eines Vogels gibt. Solche Objekte muss man sich daher selbst aus den so genannten Primitiven, wie z.B. Punkten, Linien oder Dreiecken zusammensetzen.&lt;br /&gt;
&lt;br /&gt;
OpenGL ein riesiger Zustandsautomat. Je nachdem wie Ihr die einzelnen Zustände schaltet können die Bilder, welche ihr auf dem Bildschirm ausgebt völlig unterschiedlich aussehen. Beispielsweise sieht ein Würfel mit aktiviertem Licht gezeichnet anders aus als derselbe Würfel ohne Licht. Verändert Ihr einmal einen Zustand wie z.B. die Farbe so werden sämtliche Primitive, die Ihr anschließend zeichnet mit dieser Farbe versehen, bis ihr die Farbe erneut wechselt.&lt;br /&gt;
&lt;br /&gt;
== Von Tausend und einer Funktion ==&lt;br /&gt;
 &amp;lt;pascal&amp;gt;glColor3b, glColor3d, glColor3f, glColor3i, glColor3s, &lt;br /&gt;
 glColor3ub, glColor3ui, glColor3us, glColor4b, glColor4d, &lt;br /&gt;
 glColor4f, glColor4i, glColor4s, glColor4ub, glColor4ui, &lt;br /&gt;
 glColor4us, glColor3bv, glColor3dv, glColor3fv, glColor3iv, &lt;br /&gt;
 glColor3sv, glColor3ubv, glColor3uiv, glColor3usv, &lt;br /&gt;
 glColor4bv, glColor4dv, glColor4fv, glColor4iv, glColor4sv, &lt;br /&gt;
 glColor4ubv, glColor4uiv, glColor4usv&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Es sind nicht ganz tausend und eine geworden, allerdings kommt dies schon sehr nahe dran ;). Sprach ich nicht gerade noch von einem kleinen Sprachumfang? Schnell werdet Ihr aber erkannt haben, dass das Grundgerüst dieser Funktion glColor heißt. All diese Funktionen verhalten sich gleich und unterscheiden sich lediglich in der Übergabe der Parameter. So werden bei glColor3i 3 Parameter vom Typ Integer erwartet. glColor4b verlangt hingegen 4 Parameter vom Typ Byte.&lt;br /&gt;
&lt;br /&gt;
Alle OpenGL-Funktionen besitzen den Präfix gl gefolgt von dem Befehlsstamm. Einige Funktionen besitzen noch einen Suffix, der den Typ oder auch die Anzahl der übergebenen Parameter wieder spiegelt.&lt;br /&gt;
&lt;br /&gt;
OpenGL-Konstanten sind immer an ihren Großbuchstaben erkennbar und beginnen mit der Vorsilbe GL_. Obgleich Delphi keine Unterschiede zwischen Groß- und Kleinschreibung macht empfehle ich doch diese Schreibweise beizubehalten, denn sie steigert die Übersicht ungemein.&lt;br /&gt;
== Wie sind OpenGL-Programme ausgebaut? ==&lt;br /&gt;
Um ein Dreieck zu Rendern reicht es vielleicht das Bild einmal zu Zeichnen und auszugeben. Der Großteil von Euch wird sich jedoch nicht mit einem Dreieck zufrieden geben und möchte doch wenigstens Bewegungen und Animationen in seinen Programmen verwenden. Die Vorgehensweise ist so einfach wie genial: Um Bewegungen zu ermöglichen ist es notwenig, das Bild mehrmals zu zeichnen und auszugeben. Stellt Euch vor Ihr möchtet ein Dreieck von links nach rechts über den Bildschirm bewegen! Ihr zeichnet Euer Dreieck ganz links und gebt es aus. Noch bevor das menschliche Auge genug Zeit hat dieses Bild als einzelnes Bild zu deuten habt ihr dank der hohen Geschwindigkeit der heutigen PCs das Dreieck bereits um ein paar Pixel nach rechts verschoben und erneut gezeichnet. Ist Euer Rechner schnell genug, so erscheint den Betrachter die Bewegung als völlig flüssig und die eigentlichen Sprünge von wenigen Pixeln sind als solche nicht erkennbar. Das menschliche Auge kann etwa 25-30 Bilder pro Sekunde unterscheiden, also solltet Ihr immer versuchen mehr als 30 Bilder pro Sekunde (FPS = Frames per Second) zu zeichnen. &lt;br /&gt;
&lt;br /&gt;
Spätestens jetzt sollte Euch klar sein, warum es bei modernen Spielen manchmal ruckeln kann, wenn Euer Rechner zu langsam ist.&lt;br /&gt;
&lt;br /&gt;
Soweit zur Theorie. Wie aber realisiert man diesen Vorgang. Ganz klar: Wir zeichnen in einer Schleife. Nun stellt sich die Frage wie man dieses Problem elegant löst. Man könnte sich z.B. eine eigene Hauptprogrammschleife schreiben, in der man rendert. In dieser müsste man dann aber auch die Botschaften des Betriebssystems verarbeiten.&lt;br /&gt;
&lt;br /&gt;
Eine elegantere Lösung ist meiner Meinung nach das OnIdle-Ereignis der Anwendung hierfür zu nutzen. Wenn Ihr darin den Parameter Done auf False setzt wird diese Nachricht so oft ausgeführt, wie es nur irgendwie möglich ist. Das OnIdle-Ereignis wird im Hauptthread der Anwendung aufgerufen, was den positiven Nebeneffekt hat, dass die Nachrichten des Betriebssystems von der VCL verarbeitet werden und man die VCL in vollem Umfang nutzen kann.&lt;br /&gt;
&lt;br /&gt;
Nachteil der vorgestellten Methoden ist, dass die Anwendung nie zur Ruhe kommt, da die Schleife permanent durchlaufen wird. Damit steigt die Prozessorauslastung in der Regel auf 100%. Wenn man aus bestimmten Gründen in keiner echten Schleife rendern möchte könnte man sich auch mit einem Timer Abhilfe schaffen.&lt;br /&gt;
== Die Initialisierung ==&lt;br /&gt;
Wer sofort loslegen möchte, den kann ich beruhigen, denn die Initialisierung von OpenGL ist mit unserem Header sehr einfach. Ihr müsst einfach bevor Ihr OpenGL nutzen möchtet, z.B. im OnCreate-Ereignis Eures Formulars die Funktion InitGL aufrufen, nachdem Ihr die Unit dglOpenGL in Eurer Usesklausel eingebunden habt.&lt;br /&gt;
&lt;br /&gt;
Damit OpenGL auch weiß, wohin gezeichnet werden soll müssen wir ihr das irgendwie mitteilen. Hierfür ermitteln wir den Gerätekontext unseres Formulars mit Hilfe der Funktion GetDC und dem Handle unseres Formulars.&lt;br /&gt;
&lt;br /&gt;
Anschleißend erstellen wir einen Zeichenkontext mit Hilfe der Funktion CreateRenderingContext.&lt;br /&gt;
&lt;br /&gt;
Nachdem wir diesen erstellt haben müssen wir Ihn noch aktivieren. Dies geschieht mit der Funktion ActiveRenderingContext. Das ganze sieht dann in etwa so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;var&lt;br /&gt;
  DC, RC:HDC;&lt;br /&gt;
procedure TfrmMain.FormCreate(Sender: TObject);&lt;br /&gt;
begin&lt;br /&gt;
  DC:=GetDC(Handle);&lt;br /&gt;
  RC:=CreateRenderingContext(DC, [opDoubleBuffered], 32, 24, 0, 0, 0, 0);&lt;br /&gt;
  ActivateRenderingContext(DC, RC);&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Prinzip könntet Ihr nun loslegen. Wenn Ihr Euer Bild nun im OnIdle-Ereignis zeichnet werdet Ihr schnell feststellen, dass Ihr nichts zu sehen bekommt. Das ist auch ganz normal, denn Ihr müsst das Bild doch auch ausgeben. Das geschieht mit Hilfe der Funktion SwapBuffers.&lt;br /&gt;
&lt;br /&gt;
Da wir sauber programmieren wollen müssen wir den Renderingkontext und den Gerätekontext wieder freigeben, wenn wir unser Programm beenden oder aber OpenGL nicht mehr benötigen. Die Funktionen ReleaseDC und DestroyRenderingContext erfüllen diese Aufgaben.&lt;br /&gt;
&lt;br /&gt;
Jetzt müssen wir nur noch die Größe des Bildes, welches wir rendern möchten definieren. Mit dem Befehl [[glViewport]] definieren wir die Zeichenfläche. Im Gegensatz zu Windows liegt der Ursprung bei OpenGL unten links. Da die Größe unserer Zeichenfläche der des Fensters entsprechend soll rufen wir diesen Befehl im OnResize-Ereignis unseres Formulars auf:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glViewport(0, 0, ClientWidth, ClientHeight);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die vier kommenden Zeilen solltet Ihr ganz schnell wieder aus Eurem Gedächtnis streichen und erst einmal als gegeben hinnehmen. In Tutorial 2 und 3 werden wir näher darauf eingehen. Soviel sei jedoch gesagt: Es wird nichts weiter unternommen als unsere dreidimensionale Welt aufzuspannen. Damit ist sichergestellt, dass Objekte in großer Entfernung kleiner erscheinen, so wie wir es gewohnt sein sollten.&lt;br /&gt;
&lt;br /&gt;
Mit diesem Wissen könnt Ihr nun direkt in Tutorial 2 einsteigen. &lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Genug dazu. Ich freue mich sehr, dass Ihr Euch die Zeit genommen habt, dieses Tutorial zu lesen und OpenGL lernen wollt. Ich hoffe, dass wir die nächsten Tutorials genauso gut durchbekommen und dass am Ende jeder etwas gelernt hat und die Zeit nicht total vergebens war. Ich schreibe sicherlich nicht immer alles auf dem direktesten Weg, sondern rede gerne mal um den Brei herum. Wer das nicht mag, soll sich die OpenGL-Dokumentation zu Herzen nehmen, dort ist alles kurz und schmerzlos beschrieben ;). Für alle, die es nicht so trocken mögen, ist mein Schreibstil hoffentlich eine gute Alternative ;).&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Magellan'''&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_glsl2&amp;diff=7657</id>
		<title>Tutorial glsl2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_glsl2&amp;diff=7657"/>
				<updated>2005-05-29T20:37:01Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= GLSL  Ergänzungen und Beispiele =&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Willkommen zu meinem zweiten Tutorial für die DelphiGL-Community. Da ich kein Freund großer Worte bin (was auch mein Deutsch-Kursleiter immer bemängelt ;) ) werde ich so schnell wie möglich mit dem Wichtigen beginnen. Ich werde nur schnell einiges anmerken:&lt;br /&gt;
Dieses Tutorial sollte nicht als zweiter Teil zu Sascha Willems hervorragendem ersten GLSL-Tutorial angesehen werden, sondern eher als Anhang verstanden werden. Auf keinen Fall empfiehlt es sich, sofort mit diesem Tutorial in die Materie einzusteigen. Arbeitet es einfach direkt nach dem ersten  durch als ob dieses gar nicht aufgehört hat. Zweitens soll in diesem Tutorial im Gegensatz mehr der praktische Part überwiegen. Nach der doch etwas trockenen Materie, die Sascha meiner Meinung nach exzellent aufgearbeitet hat ist etwas Praxis und Anwendung gefragt. Drittens wollte ich noch anmerken, dass ich dieses Tutorial eher als Sammlung mehrerer kleiner Tutorials als ein Großes ansehe. Die einzelnen Teile werden nur bedingt aufeinander aufbauen.&lt;br /&gt;
&lt;br /&gt;
== Ergänzungen ==&lt;br /&gt;
Im Laufe meiner eigenen, ersten Schritte im Bereich der [[Shader]]entwicklung sind mir selbst einige Dinge aufgefallen, die nicht ganz unerwähnt bleiben sollten, da sie schnell für Frust sorgen können:&lt;br /&gt;
&lt;br /&gt;
Die NVidia-Treiber und ihre Pendants von ATI sind unterschiedlich tolerant was die Compilierung der Shader-Quellcodes angeht. Aus Kompatibilitätsgründen empfehle ich durchgehend für Zahlen, die in eine Float-Variable hineingerechnet werden, keine Integerwerte zu verwenden. Ganz konkret: &lt;br /&gt;
&lt;br /&gt;
 float TestVariable = 1.0 / 2 &lt;br /&gt;
&lt;br /&gt;
ist den offiziellen Spezifikationen nach nicht zulässig. Die zwei muss wenn dann als Float (2.0) geschrieben werden. NVidia-Karten werden zwar beim Starten weder eine Warnung noch einen Fehler anzeigen, ATI-Karten weisen den Shader dagegen jedoch strikt zurück. Gewöhnt es euch deswegen an, einfach so gut wie immer &lt;br /&gt;
&lt;br /&gt;
  float TestVariable = 1.0 / 2.0&lt;br /&gt;
&lt;br /&gt;
zu schreiben.&lt;br /&gt;
&lt;br /&gt;
Da OpenGL eine Statemachine ist bleiben die Shader, wenn sie einmal per [[glUseProgramObjectARB]](LichtShader) aktiviert wurden, solange aktiv bis sie wieder per glUseProgramObjectARB(0) deaktiviert werden. Ihr könnt wirklich verdammt viel Rechenzeit sparen, wenn Ihr die Shader-Programme nur auf gewollte Objekte anwendet.&lt;br /&gt;
&lt;br /&gt;
Bei Shadern ist eine Struktur extrem wichtig, um das Ganze übersichtlich zu halten. Glaubt es mir! Vor allem am Anfang werdet ihr bei etwas komplexeren Shadern nur schwer den Überblick behalten können. Überlegt euch vielleicht ein System, wann ihr Variablen deklariert, wie ihr kommentiert usw. Shader sind hochmathematisch und oft hat man bald vergessen was eine Zeile bewirken soll, weil ihr so taktisch gerechnet habt. Dann könnte ein Hinweis nicht schaden.&lt;br /&gt;
&lt;br /&gt;
In Shadern gibt es sowas Schönes, dass schimpft sich Interpolation von varying Variablen. Durch Interpolation werden Berechungen, die im Vertexshader auf einzelne Vertices angewendet werden, automatisch im Fragmentshader für jedes Fragment angewendet.&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel: &lt;br /&gt;
&lt;br /&gt;
Wenn ihr im Vertexshader die Variable ''pos'' mit der Vertexposition belegt, dann hat sie beim Auslesen im Fragmentshader die genaue Position des Fragments. Genauso verhält es sich beispielsweise mit Texturkoordinaten. Es hat mir ganz schön Kopfzerbrechen bereitet bis ich das verstanden hatte. Eventuell ist meine Erklärung lückenhaft oder schlicht falsch. Bis jetzt hat es mir aber noch keine Probleme bereitet.&lt;br /&gt;
&lt;br /&gt;
Wer C++ kennt, der wird natürlich wissen, dass man andere Source-Files per ''#include'' einbinden kann. Damit kann man seine Shader sehr schön strukturieren.&lt;br /&gt;
&lt;br /&gt;
Noch ein paar Informationen zu [[glUniform]] bzw. [[glVertexAttrib]] die einem sehr viel Kopfzerbrechen bereiten können. Bildlich gesprochen bezieht sich glUniform nämlich auf ganze Polygone, hat seinen Platz also vor [[glBegin]]. Wird es in einem glBegin/glEnd-Block eingesetzt wird zwar kein Fehler angezeigt aber die Werte werden einfach nicht übergeben. Natürlich braucht man auch eine Funktion wie glVertexAttrib, die Werte für einen Vertex setzt. Diese Funktion kann dann ruhig auf jeden Vertex mit anderen Werten angewendet werden. Einen kleinen Nachteil gibt es aber trotzdem. Sobald ihr  glVertexAttrib verwendet, werden [[glVertex]], [[glNormal]] und [[glTexCoord]] nutzlos. Diese Funktionen machen eigentlich auch nichts anderes als Vertexattribute zu setzen. Nun hat man die Wahl. Entweder man übergibt auch Position, Normalen und Texturkoordinaten über glVertexAttrib oder man wendet Trick 17 an und übergibt Vertexattribute mit Multitexturkoordinaten. Die kann man dann im Shader ganz bequem auslesen. Vielen Dank an Lars Middendorf für diesen Tipp!&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
=== Ein Shader, der die Hardware T&amp;amp;L- Einheit simuliert ===&lt;br /&gt;
Fangen wir mit einer einfachen Aufgabe an. Dem schrittweisen Aufbau eines Shaders, der eigentlich nichts anderes macht als das, was OpenGL ohne Shader auch machen würde. Ziemlich sinnlos ;). Aber ich glaube als Übung bietet sich das recht schön an. Beginnen wir mit dem leeren Shader, der nur das Nötigste enthält:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Fragmentshader:&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  gl_FragColor = 1.0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Wer in Saschas Tutorial aufgepasst hat, dem dürfte klar sein, dass dieser Vertexshader jeden Vertex an seine Position setzt und der Fragmentshader jedes zu einem Polygon gehörende [[Pixel]] weiss einfärbt. Nun kommt schon der nächste Schritt: Wir färben das Polygon nicht mehr weiss sondern mit der Farbe, die wir in OpenGL immer per [[glColor]] angeben. Ein kurzer Blick in die Referenz offenbart uns die vordeklarierte Variable ''gl_FrontColor''. Dieser übergeben wir jetzt im Vertexshader den Wert ''gl_Color''. Das ist die Farbe, die wir im Programmcode per glColor angegeben haben:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&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;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Im [[Fragment]]shader lesen wir den Wert, den wir im Vertexshader an ''gl_FrontColor'' gegeben haben, wieder mit ''gl_Color'' aus.&lt;br /&gt;
&lt;br /&gt;
Fragmentshader:&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  gl_FragColor = gl_Color;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_glsl_ext_schritt1.jpg|256px]]&lt;br /&gt;
&lt;br /&gt;
Voilà! Das ist ja schon einmal ein schöner Anfang. Aber in welchem 3D-Programm gibt es bloß einfarbige Polygone? Also müssen wir jetzt noch Texturen hinzufügen. Erst einmal arbeiten wir nur mit einer Textureinheit. Wie gewohnt ladet ihr eine Textur, bindet diese per [[glBindTexture]] und weist ihr Koordinaten zu. Den Vertexshader lassen wir jetzt erst einmal die Texturkoordinaten auslesen:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&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;
&lt;br /&gt;
Diese Koordinate wird dann interpoliert und der Fragmentshader liest dann für jedes Fragment mit diesen Koordinaten die Textur aus und gibt ''gl_FragColor'' die Farbe. Dazu deklarieren wir am Anfang eine uniform-Variable für die Textur. Vorerst übergeben wir aus dem Programmcode dieser Variable keinen Wert. Ich werde später darauf zurückkommen. Sie teilt dem Fragmentshader nur mit in welcher Textureinheit er nach der Textur suchen soll. In diesem Fall ist der Wert also 0, bzw. ein Pointer auf die Textur in der Einheit 0. Fragt mich aber nicht, warum man diesen Wert nicht direkt eingeben kann O_o!&lt;br /&gt;
&lt;br /&gt;
Fragmentshader:&lt;br /&gt;
 uniform sampler2D Texture0;&lt;br /&gt;
&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  gl_FragColor = texture2D(Texture0, vec2(gl_TexCoord[0]));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_glsl_ext_schritt2.jpg|256px]]&lt;br /&gt;
&lt;br /&gt;
Sieht ja schon einmal recht ansehnlich aus. Ohne viele Umschweife komme ich gleich zum [[Multitexturing]]. Dazu müssen wir zuerst in unseren Programmcode gehen. Hier belegen wir zwei Textureinheiten mit....ja...mit Texturen (immer diese verdammten Wiederholungen, mein Deutschkursleiter würde mich hauen). Danach kommt wieder etwas Spezifisches zu Shadern: &lt;br /&gt;
Wir weisen den uniform-Variablen (''uniform sampler2D Texture0'') im Shader ihre Textureinheit zu.&lt;br /&gt;
&lt;br /&gt;
Programmcode:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glActiveTexture(GL_TEXTURE0);&lt;br /&gt;
glBindTexture(GL_TEXTURE_2D, Textur);&lt;br /&gt;
glActiveTexture(GL_TEXTURE1);&lt;br /&gt;
glBindTexture(GL_TEXTURE_2D, Textur2);&lt;br /&gt;
&lt;br /&gt;
glUniform1iARB(glGetUniformLocationARB(shader, 'Texture0'), 0);&lt;br /&gt;
glUniform1iARB(glGetUniformLocationARB(shader, 'Texture1'), 1);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun geht es wieder ab in den Shadercode. Wieder übergeben wir hier nur die Texturkoordinaten. Wenn für die unterschiedlichen Textureinheiten dieselben Texturkoordinaten gesetzt wurden würde der Shader von vorhin ausreichen. So spart man sich eine Zeile. Soviel zur Optimierung ;).&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&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;
  gl_TexCoord[1] = gl_MultiTexCoord1;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Im Fragmentshader auch nichts wirklich Neues. Wir binden die zweite Textur ein und bringen sie mit ''gl_FragColor'' ins Spiel. Ich hab im Beispielcode einfach mal beide Texturen multipliziert aber ihr könnt damit eigentlich anstellen was ihr wollt. Probiert einfach mal ein paar Sachen aus!&lt;br /&gt;
&lt;br /&gt;
Fragmentshader:&lt;br /&gt;
 uniform sampler2D Texture0;&lt;br /&gt;
 uniform sampler2D Texture1;&lt;br /&gt;
&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  gl_FragColor = texture2D(Texture0, vec2(gl_TexCoord[0]))&lt;br /&gt;
               * texture2D(Texture1, vec2(gl_TexCoord[1]));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_glsl_ext_schritt3.jpg|256px]]&lt;br /&gt;
&lt;br /&gt;
Sodala, is ja schon was. *überleg* was gehört denn noch zur Standard-OGL-Ausrüstung? Hmm, achja, Licht! OpenGL arbeitet ja normalerweise nur mit Per-Vertex-Berechnungen. Das wird schon ein bisschen anspruchsvoller. Wir werden ein wenig Mathematik betreiben müssen. Aber das werden wir schon wuppen! Außerdem ist mir aufgefallen, dass wenn man das ganze selber gemacht hat man das OpenGL-Licht auch gleich viel besser versteht. Als erstes empfehle ich euch einen Blick in folgendes Dokument von Tom Nuydens:&lt;br /&gt;
[http://www.delphi3d.net/articles/viewarticle.php?article=phong.htm Phong For Dummies]&lt;br /&gt;
&lt;br /&gt;
In diesem Dokument erhaltet ihr einen Einblick in das derzeit meist verwendete Beleuchtungsmodell. Es ist nicht perfekt realistisch, kommt dem aber recht nahe und ist sehr ressourcensparend. Wichtig ist für uns hier nur der Diffuse-Term. Diese Gleichung sagt uns im Prinzip nur, ob ein Vertex beleuchtet wird oder nicht. Außerdem werden die Ränder schön gefadet. Mit Per-Pixel-Lighting kommt dann später noch der Specular-Term dazu, der die Oberfläche glänzen lässt. Weil die Glanzfläche so klein ist macht das hier aber noch keinen Sinn, denn die Wahrscheinlichkeit, dass sie auf ein Vertex fällt ist ziemlich gering.&lt;br /&gt;
&lt;br /&gt;
Nun aber ran an die Arbeit. Als erstes baut ihr in eurem Programmcode die Standard-OpenGL-Beleuchtung ganz ohne Shader ein und schaut, ob es funktioniert. Damit können mögliche Fehler nur noch am Shadercode liegen. Dann bindet ihr den Shader ein. Für die Berechnung brauchen wir zwei Vektoren: Den Vektor von unserem Vertex zur Lichtquelle und die Flächennormale. Um Ersteren zu berechnen, multiplizieren wir die Position unseres Vertex mit der Modelviewmatrix und subtrahieren das Ergebnis von der Position der Lichtquelle (''gl_LightSource[0].position''):&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  ...&lt;br /&gt;
  vec3 Position = vec3(gl_ModelViewMatrix * gl_Vertex);&lt;br /&gt;
  vec3 Light = vec3(normalize(vec3(gl_LightSource[0].position) - Position));&lt;br /&gt;
  ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Die Flächennormale können wir im Vertexshader jedoch nicht berechnen, da dieser nur mit einzelnen Vertices arbeiten kann, für die Berechnung aber mindestens drei notwendig sind. Also berechnen wir sie im Programmcode. Wie das geht, steht in folgendem DGL-Tutorial: [[tutorial_linearealgebra1|Lineare Algebra]].&lt;br /&gt;
Im Programmcode übergebt ihr die Normale wie gewohnt per glNormal und im Shader lesen wir sie dann ganz einfach mit ''gl_Normal'' aus. Die Normale multiplizieren wir noch schnell mit der Normalmatrix:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&lt;br /&gt;
 ...&lt;br /&gt;
 vec3 Normal = normalize(gl_NormalMatrix * gl_Normal);&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
Nun können wir endlich die Beleuchtung berechnen. Wie der ein oder andere bereits wissen dürfte, setzt sich die Beleuchtung in dem von unserem verwendeten Modell aus dem Ambient- und dem Diffuse-Term zusammen. Der Ambient-Term bestimmt eigentlich nur was für eine Farbe ein Pixel haben soll, der überhaupt nicht beleuchtet wird. Den berechnen wir einfach indem wir den Ambient-Wert der Lichtquelle mit dem des Materials multiplizieren:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&lt;br /&gt;
 ...&lt;br /&gt;
 vec3 Ambient = vec3(gl_FrontMaterial.ambient) * vec3(gl_LightSource[0].ambient);&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
So. Nun kommt der Clou des Ganzen: Wir berechnen den Diffuse-Term! Aus dem oben verlinkten Dokument von Delphi3D.net holen wir uns folgende Formel:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&lt;br /&gt;
 ...   &lt;br /&gt;
 Diffuse = max(dot(Normal, Light), 0.0);&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
Die Funktion ''dot'' berechnet eigentlich nur den Kosinus des Winkels zwischen den beiden Vektoren Normal und Light (mehr dazu in o.g. Tutorial von DGL). Dadurch bekommen wir automatisch einen nichtlinearen Verlauf der Beleuchtung. ''max'' vergleicht die Werte x und y und liefert automatisch den höheren der beiden zurück. So erreichen wir, dass wir keinen Wert kleiner 0 bekommen. Damit auch das diffuse Licht eine Farbe bekommt multiplizieren wir noch schnell mit den jeweiligen Farben der Lichtquelle und des Materials:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&lt;br /&gt;
 ...&lt;br /&gt;
 Diffuse *= gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse;&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
Dann weisen wir gl_FrontColor nur noch die Werte zu, die wir berechnet haben und geben dem Ganzen noch eine vierte Dimension:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&lt;br /&gt;
 ...&lt;br /&gt;
 gl_FrontColor = vec4(Diffuse + Ambient, 1.0);&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
Nun noch schnell im Fragmenthader gl_FragColor einen Wert zuweisen:&lt;br /&gt;
&lt;br /&gt;
Fragmentshader:&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  gl_FragColor = gl_Color;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Die Anfangs erwähnte Interpolation sorgt automatisch dafür, dass die Farbe von Vertex zu Vertex schön weich verläuft.&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_glsl_ext_schritt4.jpg|256px]]&lt;br /&gt;
&lt;br /&gt;
Warum die Farben nicht ganz mit der OpenGL-hauseigenen Beleuchtung zusammenpassen, kann ich leider nicht sagen. Zum Abschluss möchte ich euch gerne noch zeigen, wie ihr per Shader Cubemaps einbaut, vor allem für so schöne Effekte, wie spiegelndes Wasser solltet ihr diese Technik schon beherrschen. Da ich euch nicht mit dem Laden der Cubemap langweiligen will, fangen wir in der Renderprozedur an. Ein geeigneter Loader für die Texturen wäre beispielsweise eine modifizierte Version von Lossy eX' glBitmap (Siehe Anhang).&lt;br /&gt;
Im Quelltext binden wir einfach die Cubemap für die glBitmap üblich mit FCubeMap.Bind;&lt;br /&gt;
Das Objekt, auf welches draufprojeziert werden soll muss Texturkoordinaten und eine Normale haben. Das sollte eigentlich kein Problem sein. Nun kommt der Shader dran. Wir deklarieren wieder eine uniform-Textur, diesmal aber nicht ''sampler2D'' sondern ''samplerCube''. Eigentlich logisch. Um jetzt für jedes Pixel unseres Polygons den geeigneten Wert aus der Cubemap auszulesen nehmen wir die normale Texturkoordinate und addieren die Flächennormale dazu. Dass ergibt wiederum eine dreidimensionale Texturkoordinate, die wir in die Shaderfunktion ''textureCube'' einlesen, die sich fast genauso wie ''texture2D'' benutzen lässt:&lt;br /&gt;
&lt;br /&gt;
Fragmentshader:&lt;br /&gt;
 uniform samplerCube Texture0;&lt;br /&gt;
&lt;br /&gt;
 varying vec3 normal;&lt;br /&gt;
&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  vec3 TexCoord = vec3(gl_TexCoord[0]);&lt;br /&gt;
  gl_FragColor= textureCube(Texture0, normal + TexCoord);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_glsl_ext_schritt5.jpg|256px]]&lt;br /&gt;
&lt;br /&gt;
Damit haben wir unsere selbstprogrammierte Hardware T&amp;amp;L-Einheit schon fertig! War doch gar nicht so schlimm. Im Folgenden entfernen wir uns dann ein bisschen von der herkömmlichen Programmiererei und machen mal ein paar schöne Effekte.&lt;br /&gt;
&lt;br /&gt;
=== Per-Pixel-Lighting ===&lt;br /&gt;
Ein wirklich schöner Effekt, den man auch in Spielen bisher recht selten sieht. &lt;br /&gt;
Eigentlich haben wir im Per-Vertex-Lighting schon alles gemacht. Wir müssen nun nur unsere Berechnungen, die wir Per-Vertex durchgeführt haben, in den Fragmentshader verlegen. Und dann berechnen wir noch den Specularwert, der angibt wie sich das Licht spiegelt und zurückgeworfen bzw. dem Betrachter zugeworfen wird. Um diesen Wert zu berechnen gibt es zwei Lösungsmöglichkeiten, die sich aber nicht sehr unterscheiden. Es handelt sich um sogenanntes Phong bzw Blinn-Phong Lighting. Wir werden Phong-Lighting einbauen, das Blinn-Phong könnt ihr ja als Übungsaufgabe machen ;). Die geometrischen Grundlagen findet ihr wieder in oben genanntem Artikel von Delphi3D.&lt;br /&gt;
Für uns wichtig sind folgende Formeln:&lt;br /&gt;
&lt;br /&gt;
 Reflected = 2 * (Normal  Light) * Normal - Light&lt;br /&gt;
&lt;br /&gt;
und&lt;br /&gt;
&lt;br /&gt;
 Specular = SpecularLight * SpecularMaterial * pow(max(dot(Reflected, Eye), 0), Shininess)&lt;br /&gt;
&lt;br /&gt;
Wie der Name vermuten lässt berechnen wir mit der ersten Formel den an der Oberfläche reflektierten Lichtvektor. Mit der zweiten vergleichen wir dann diesen Vektor mit dem des Beobachters.&lt;br /&gt;
Im Vertexshader berechnen wir die einzelnen Vektoren, die dann wie üblich interpoliert werden:&lt;br /&gt;
&lt;br /&gt;
Vertexshader:&lt;br /&gt;
 varying vec3 normal;&lt;br /&gt;
 varying vec3 v;&lt;br /&gt;
 varying vec3 lightvec;&lt;br /&gt;
&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
   normal          = normalize(gl_NormalMatrix * gl_Normal);&lt;br /&gt;
   v               = vec3(gl_ModelViewMatrix * gl_Vertex);&lt;br /&gt;
   lightvec        = normalize(gl_LightSource[0].position.xyz - v);&lt;br /&gt;
   gl_Position     = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Im Fragmentshader bringen wir jetzt die Berechnungen aus dem Per-Vertex-Lighting und die des Specular zusammen:&lt;br /&gt;
&lt;br /&gt;
Fragmentshader:&lt;br /&gt;
 varying vec3 normal;&lt;br /&gt;
 varying vec3 v;&lt;br /&gt;
 varying vec3 lightvec;&lt;br /&gt;
&lt;br /&gt;
 void main(void)&lt;br /&gt;
 {&lt;br /&gt;
  vec3 Eye             = normalize(-v);&lt;br /&gt;
  vec3 Reflected       = normalize( 2.0 * dot(normal, lightvec) *  normal - lightvec);&lt;br /&gt;
  vec4 IAmbient        = gl_LightSource[0].ambient;&lt;br /&gt;
  vec4 IDiffuse        = gl_LightSource[0].diffuse * max(dot(normal, lightvec), 0.0);&lt;br /&gt;
  vec4 ISpecular       = gl_LightSource[0].specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess);&lt;br /&gt;
  gl_FragColor         = gl_FrontLightModelProduct.sceneColor + IAmbient + IDiffuse + ISpecular;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_glsl_ext_perpixellicht.jpg|256px]]&lt;br /&gt;
&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Sodala. Fertig! Ich hoffe, ihr habt etwas gelernt und ich all' eure Fragen beantworten konnte. Wenn nicht, dann werden wir euch im DGL-Forum Rede und Antwort stehen. Auch Kritik ist dort gern gesehen, denn nur so können zukünftige Tutorials weiter an Qualität gewinnen. Ich würde mich auch sehr freuen, wenn ihr im Shaderforum eure Ergebnisse postet, egal wie langweilig sie auch seien mögen  ihr beherrscht jetzt immerhin Shader :-).&lt;br /&gt;
Also, ich packs jetzt, sonst packts mich.&lt;br /&gt;
&lt;br /&gt;
'''Euer''' &amp;lt;br&amp;gt;&lt;br /&gt;
'''La_Boda''' (-pdl-@web.de)&lt;br /&gt;
&lt;br /&gt;
== Anhang ==&lt;br /&gt;
&lt;br /&gt;
[http://www.dev-center.de/ dev-center] -  Hier könnt Ihr das die Unit glBitmap finden&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_perpixellicht.jpg&amp;diff=12937</id>
		<title>Datei:Tutimg glsl ext perpixellicht.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_perpixellicht.jpg&amp;diff=12937"/>
				<updated>2005-05-29T20:23:00Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt5.jpg&amp;diff=12936</id>
		<title>Datei:Tutimg glsl ext schritt5.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt5.jpg&amp;diff=12936"/>
				<updated>2005-05-29T20:22:47Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt4.jpg&amp;diff=12935</id>
		<title>Datei:Tutimg glsl ext schritt4.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt4.jpg&amp;diff=12935"/>
				<updated>2005-05-29T20:22:34Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt3.jpg&amp;diff=12934</id>
		<title>Datei:Tutimg glsl ext schritt3.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt3.jpg&amp;diff=12934"/>
				<updated>2005-05-29T20:22:24Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt2.jpg&amp;diff=12933</id>
		<title>Datei:Tutimg glsl ext schritt2.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt2.jpg&amp;diff=12933"/>
				<updated>2005-05-29T20:22:11Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt1.jpg&amp;diff=12932</id>
		<title>Datei:Tutimg glsl ext schritt1.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_glsl_ext_schritt1.jpg&amp;diff=12932"/>
				<updated>2005-05-29T20:21:55Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Quickstart&amp;diff=7878</id>
		<title>Tutorial Quickstart</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Quickstart&amp;diff=7878"/>
				<updated>2005-05-21T13:34:37Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: Rechtschreibfehler&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Quickstart: Delphi &amp;amp; OpenGL=&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Willkommen beim Delphi &amp;amp; OpenGL Quickstart. Diese kurze Einleitung soll Euch auf die Tutorials bei DelphiGL.com und allgemein auf die Grafikprogrammierung mit OpenGL und Delphi vorbereiten. Dieser Quickstart ist kein Tutorial für sich, sondern soll ein Grundgefühl vermitteln wie OpenGL und Delphi miteinander arbeiten.&lt;br /&gt;
&lt;br /&gt;
Wozu OpenGL?  Mit OpenGL kann man eine Vielzahl von Aufgaben bewältigen. Ob man Forschungsergebnisse aller Art visualisieren, 2D oder 3D Spiele schreiben oder einfach seiner Anwendung eine Oberfläche geben möchte, die nicht dem windowsgrauen Standardlook entspricht. All das ist möglich mit OpenGL.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wie fange ich an?==&lt;br /&gt;
Genau zwei Dinge braucht der OpenGL-Programmierer um effektiv  arbeiten zu können:&lt;br /&gt;
#Einen OpenGL Header&lt;br /&gt;
#Eine Codebasis von der aus man neue Projekte starten kann (ein sog. Template)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Der OpenGL-Header===&lt;br /&gt;
Das is ja easy! Denn Delphi bringt ja schon einen OpenGL-Header mit... &amp;lt;br&amp;gt;&lt;br /&gt;
'''STOP!''' &amp;lt;br&amp;gt;&lt;br /&gt;
Denn wir reden von einem guten Header. Leider ist der original von Delphi mitgelieferte Header alles andere als zu empfehlen. Er ist fehlerhaft, hält sich nicht an OpenGL-Normen und außerdem ist er absolut veraltet. &amp;lt;br&amp;gt;&lt;br /&gt;
Was nun?  Ganz einfach: Bei [http://www.DelphiGL.com DelphiGL.com] (kurz DGL) gibt es '''DEN''' OpenGL-Header für alle Pascalsprachen: &lt;br /&gt;
'''Die [[DGLOpenGL.pas]].'''&lt;br /&gt;
&lt;br /&gt;
Diesen solltet Ihr Euch jetzt besorgen, wenn Ihr ihn nicht schon habt. Der Header wird bei neuen OpenGL-Versionen vom DGL-Team aktualisiert. &lt;br /&gt;
&lt;br /&gt;
===Codebasis/Templates===&lt;br /&gt;
So... das war schon alles was Ihr aus dem Netz benötigt. Den Rest machen wir jetzt per Hand.&lt;br /&gt;
&lt;br /&gt;
Im nächsten Kapitel zeige ich Euch wie man sich ein einfaches Template schreibt. Natürlich hat DelphiGL.com auch bereits fertige Lösungen, die durchaus zu empfehlen sind und auch extra Features wie Vollbildrendering besitzen. ABER aus Erfahrung kann ich sagen: Man findet sich im eigenen Code viel einfacher zurecht. (Und die Extras kann man nachher immer noch einbauen.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Das Template  Oder Delphi fit für OpenGL machen==&lt;br /&gt;
Bevor man wirklich loslegen kann, muss noch die runtergeladene DGLOpenGL.pas an den richtigen Ort gebracht werden. Gut wäre z.B. sie in das Verzeichnis &amp;quot;\lib&amp;quot; in Eurem Delphiverzeichnis zu legen. (Wenn ihr den DGLSDK verwendet wurden die Suchpfade schon eingerichtet.)&lt;br /&gt;
&lt;br /&gt;
Dann startet mal Delphi. Vor Euch sollte jetzt ein leeres Projekt erscheinen. Das leere Formular kann gleich minimiert werden, denn jetzt wird erstmal hübsch gecodet.&lt;br /&gt;
&lt;br /&gt;
===Initialisieren von OpenGL===&lt;br /&gt;
Dieser Teil ließ früher dem OpenGL Anfänger die Haare nicht nur zu Berge stehen, sondern gleich ausfallen. Dank der DGLOpenGL.pas wurde das aber um Längen einfacher. &lt;br /&gt;
&lt;br /&gt;
Zuerst einmal solltet Ihr die DGLOpenGL.pas in die '''uses'''-Klausel des '''interface'''-Teils der Unit1 schreiben.&lt;br /&gt;
&lt;br /&gt;
Die eigentliche Initialisierung soll direkt beim Erstellen des Formulars gemacht werden. Deshalb kommt der folgende Quelltext ins OnCreate-Ereignis des Formulars.&lt;br /&gt;
&amp;lt;pascal&amp;gt;procedure TForm1.FormCreate(Sender: TObject);&lt;br /&gt;
begin&lt;br /&gt;
  DC:= GetDC(Handle);&lt;br /&gt;
  if not InitOpenGL then Application.Terminate;&lt;br /&gt;
  RC:= CreateRenderingContext( DC,&lt;br /&gt;
                               [opDoubleBuffered],&lt;br /&gt;
                               32,&lt;br /&gt;
                               24,&lt;br /&gt;
                               0,0,0,&lt;br /&gt;
                               0);&lt;br /&gt;
  ActivateRenderingContext(DC, RC);&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
'''Zeile 3:''' Hier wird der Gerätekontext (Device Context) von Formular Form1 abgefragt.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 4:''' Mit InitOpenGL wird OpenGL initialisiert. Wenn das nicht funktioniert wird die gesamte Anwendung sofort beendet. &lt;br /&gt;
&lt;br /&gt;
'''Zeile 5:''' Hier wird der RenderingContext erzeugt. Den braucht OpenGL zum Zeichnen auf das Formular. Was die Parameter genau bewirken lernt ihr im [[Tutorial_lektion1]].&lt;br /&gt;
&lt;br /&gt;
'''Zeile 11:''' Abschließend wird der RenderingContext aktiviert. OpenGL ist jetzt prinzipiell startbereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach dieser durchaus simplen Initialisierung (man kann auch alles per Hand machen was InitOpenGL macht!) steht OpenGL ziemlich nackt da. Soll heißen, alle OpenGL Eigenschaften/Zustände stehen auf den definierten Anfangswerten. Es kommt aber durchaus oft - eigentlich ständig - vor, dass bestimmte Einstellungen von OpenGL benutzt werden sollen. Deshalb schreiben wir uns noch eine kleine Zusatzprozedur: SetupOpenGL&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;procedure TForm1.SetupGL;&lt;br /&gt;
begin&lt;br /&gt;
  glClearColor(0.3, 0.4, 0.7, 0.0); //Hintergrundfarbe&lt;br /&gt;
  glEnable(GL_DEPTH_TEST);          //Tiefentest aktivieren&lt;br /&gt;
  glEnable(GL_CULL_FACE);           //Backface Culling aktivieren&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was hier passiert wird durch die Kommentare bereits erklärt (Für mehr Infos siehe [[Tiefentest]] bzw. [[Backface Culling]]). Die Hintergrundfarbe könnt ihr nach Belieben einstellen. (Wenn ihr später einmal geschlossene Szenen rendern wollt, dann ist es günstig eine sehr schräge Farbe als Hintergrundfarbe einzustellen, so findet man leichter Fehler in der Szene.)&lt;br /&gt;
&lt;br /&gt;
Außerdem hat man ja hin und wieder auch noch globale Variablen, die man initialisieren möchte. Da wir mit solchen Sachen unser schön aufgeräumtes '''FormCreate''' nicht zumüllen wollen bietet sich ein Unterprogramm namens '''InitGlobals''' oder kurz '''Init''' an.&lt;br /&gt;
Beide Unterprogramme (SetupGL und Init) sollten am Ende von '''FormCreate''' gerufen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;  []&lt;br /&gt;
  ActivateRenderingContext(DC, RC);&lt;br /&gt;
  SetupGL;&lt;br /&gt;
  Init;&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Die Ereignisbehandlung===&lt;br /&gt;
Für OpenGL sind vor allem die Ereignisse von Bedeutung, die an der Zeichenfläche von OpenGL herumwerkeln. Da OpenGL direkt auf das Formular (oder auch auf ein Panel) zeichnet, müssen Ereignisse, die diese Zeichenfläche ändern, behandelt werden. Dies wären das '''OnCreate-''' und das '''OnDestroy'''-Ereignis.&lt;br /&gt;
&lt;br /&gt;
Zuerst '''FormResize''':&lt;br /&gt;
&amp;lt;pascal&amp;gt;procedure TForm1.FormResize(Sender: TObject);&lt;br /&gt;
var tmpBool : Boolean;&lt;br /&gt;
begin&lt;br /&gt;
  glViewport(0, 0, ClientWidth, ClientHeight);&lt;br /&gt;
  glMatrixMode(GL_PROJECTION);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  gluPerspective(45.0, ClientWidth/ClientHeight, NearClipping, FarClipping);    &lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_MODELVIEW);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  IdleHandler(Sender, tmpBool);&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Außerdem müssen im '''const'''  Teil die beiden Konstanten Near- bzw. FarClipping definiert werden. Diese geben die Entfernung für die [[Clipping Plane|Clippingebenen]] (Szenenbegrenzung) an.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;  NearClipping = 1;&lt;br /&gt;
  FarClipping  = 1000;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Zu FormResize''':&amp;lt;br&amp;gt;&lt;br /&gt;
'''Zeile 2:''' Diese Boolean-Variable wird in Zeile 11 verwendet und ist nur ein Dummy.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 4:''' Mittels [[glViewport]] sagt Ihr OpenGL wie groß die OpenGL-Ausgabe werden soll. Genau diese Größe hatte sich ja durch das Resize verändert.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 5/9:''' Hier seht Ihr 2 der 3 möglichen Matrixmodi. '''GL_PROJECTION''' wird benutzt um nachfolgend die OpenGL-Ausgabe zu manipulieren, '''GL_MODELVIEW''' benutzt man um OpenGL mit Daten zu füttern.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 6:''' [[glLoadIdentity]] füllt die aktuelle Matrix mit der Identitätsmatrix. &lt;br /&gt;
&lt;br /&gt;
'''Zeile 7:''' Hier wird eingestellt wie der Betrachter die Welt sehen soll. &lt;br /&gt;
&lt;br /&gt;
'''Zeile 11:''' Was der IdleHandler macht kommt später im Abschnitt 1.3.3 (Zeichenroutine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nun noch schnell das '''FormDestroy''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;procedure TForm1.FormDestroy(Sender: TObject);&lt;br /&gt;
begin&lt;br /&gt;
  DeactivateRenderingContext;&lt;br /&gt;
  DestroyRenderingContext(RC);&lt;br /&gt;
  ReleaseDC(Handle, DC);&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was es macht? Steht doch da: Den RenderingContext deaktivieren und freigeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Die Zeichenroutine===&lt;br /&gt;
Das Herzstück unseres Templates fehlte bisher. Irgendwann muss der Grafikkarte ja auch gesagt werden, was sie denn überhaupt ausgeben soll. Das kommt jetzt: '''TForm1.Render'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;procedure TForm1.Render;&lt;br /&gt;
begin&lt;br /&gt;
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);&lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_PROJECTION);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
  gluPerspective(45.0, ClientWidth/ClientHeight, NearClipping, FarClipping);&lt;br /&gt;
&lt;br /&gt;
  glTranslatef(0, 0, -5);&lt;br /&gt;
&lt;br /&gt;
  glMatrixMode(GL_MODELVIEW);&lt;br /&gt;
  glLoadIdentity;&lt;br /&gt;
&lt;br /&gt;
  glBegin(GL_QUADS);&lt;br /&gt;
    glColor3f(1, 0, 0); glVertex3f(0, 0, 0);&lt;br /&gt;
    glColor3f(0, 1, 0); glVertex3f(1, 0, 0);&lt;br /&gt;
    glColor3f(0, 0, 1); glVertex3f(1, 1, 0);&lt;br /&gt;
    glColor3f(1, 1, 0); glVertex3f(0, 1, 0);&lt;br /&gt;
  glEnd;&lt;br /&gt;
&lt;br /&gt;
  SwapBuffers(DC);&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Zeile 3:''' Dieser Aufruf sorgt dafür, dass der [[Farbpuffer]] und [[Tiefenpuffer]] gelöscht werden. Wenn man das nicht macht, sieht man alles mögliche, nur nicht das was Ihr rendern wollt. Probiert es ruhig mal ohne aus! Man wird dadurch nicht dümmer.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 7:''' Hier wird wieder die Perspektive gesetzt. Dieser Aufruf und der bei '''FormResize''' &lt;br /&gt;
müssen von den Parametern identisch sein. Sonst sieht die Ausgabe nach einem Resize kurz anders aus. &lt;br /&gt;
Wenn sich die Perspektive zwischen den Renderdurchgängen nicht ändert kann das auch weg gelassen werden.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 9:''' Dieser Aufruf verschiebt die &amp;quot;Kamera&amp;quot; (so etwas gibt es eigentlich nicht, aber da wir &lt;br /&gt;
uns gerade in der GL_PROJECTION Matrix befinden passt diese Beschreibung am besten) etwas nach hinten. Schließlich wollen wir das, was wir zeichnen auch sehen. Alles was zu nah ist wird durch die '''Near-[[Clipping Plane]]''' abgeschnitten.&lt;br /&gt;
&lt;br /&gt;
[[Bild:glShadeModel_SMOOTH.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
'''Zeile 14:''' [[glBegin]]/[[glEnd]] kapseln die eigentlichen Zeichenbefehle. Diese sorgen hier für ein '''hübsches buntes Viereck'''. Das soll für den ersten Test ausreichen. Wichtig ist in dem Zusammenhang noch folgendes: OpenGL ist es egal woher ein Befehl kommt. Alles wird ausgewertet und landet unter Umständen im Framebuffer. Ihr könnt also ein Unterprogramm, welches ein Unterprogramm, welches ... ..., welches die OpenGL Befehle enthält schreiben. Das interessiert OpenGL bzw. die Grafikkarte überhaupt nicht.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 21:''' [[SwapBuffers]] sorgt Ihr dafür, dass der Inhalt des [[Framebuffer]]s auf dem &lt;br /&gt;
Bildschirm erscheint. Ohne diesen Befehl seht Ihr gar nichts von OpenGL. (Interessanter Artikel dazu: [[Doppelpufferung]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So...ganz toll. Jetzt habt Ihr Eure Zeichenfunktion ... und nun? Irgendwie müsst Ihr diese auch aufrufen. Das wäre aber zu einfach. Die Ausgabe ändert sich ja normalerweise (z.B. in Spielen). Deshalb muss die Zeichenfunktion immer wieder ausgegeben werden. Dazu gibt es zwei Möglichkeiten, die beide Ihre Vor- und Nachteile haben.&lt;br /&gt;
&lt;br /&gt;
{|rules=&amp;quot;all&amp;quot; cellpadding=&amp;quot;5&amp;quot;&lt;br /&gt;
!Argument&lt;br /&gt;
!Timer&lt;br /&gt;
!OnIdle&lt;br /&gt;
|-&lt;br /&gt;
|Maximale Framezahl erreichbar &amp;lt;br&amp;gt;&amp;quot;Benchmark&amp;quot;&lt;br /&gt;
|nein&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
|Framezahl steuerbar&lt;br /&gt;
|ja&lt;br /&gt;
|bedingt (/umständlich)&lt;br /&gt;
|-&lt;br /&gt;
|Für flüssige Animationen nutzbar&amp;lt;br&amp;gt;(Egoshooter)&lt;br /&gt;
|bedingt/schlecht&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
|Für Menüs nutzbar&lt;br /&gt;
|ja&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
|Für einfache Animationen nutzbar&amp;lt;br&amp;gt;(Strategiespiele)&lt;br /&gt;
|ja&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
|Laptopfreundlich (Anti-Akku-Killer)&lt;br /&gt;
|ja&lt;br /&gt;
|NEIN!&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wer einfache Anwendungen schreiben möchte, die auch mit 25 FpS (Bilder Pro Sekunde) auskommen und den Akku von Laptopusern schonen will, sollte die Timervariante nutzen. Wer die Potenziale der Grafikkarten voll ausnutzen möchte sollte OnIdle verwenden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Methode 1: Timer====&lt;br /&gt;
Bei dieser Methode muss ein Timer (zu finden bei den Systemkomponenten) auf das Formular gezogen werden. Der Timer besitzt eine Eigenschaft names &amp;quot;Interval&amp;quot;. Mit dieser Eigenschaft kann man einstellen  nach wie vielen Millisekunden das Ereignis OnTimer ausgelöst wird. Man kann &amp;quot;Interval&amp;quot; nicht beliebig verkleinern. Werte unter 25 können vom Standardtimer den Windows verwendet nicht mehr korrekt erzeugt werden.&lt;br /&gt;
&lt;br /&gt;
Der Inhalt von OnTimer könnte dieser sein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;procedure TForm1.Timer1Timer(Sender: TObject);&lt;br /&gt;
begin&lt;br /&gt;
   inc(FrameCount);&lt;br /&gt;
   Render;&lt;br /&gt;
   If FrameCount = 20 then&lt;br /&gt;
      begin&lt;br /&gt;
           ErrorHandler;&lt;br /&gt;
           FrameCount := 0;&lt;br /&gt;
      end;&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tiefgreifende Erklärungen sind hier nicht notwendig. Was der ErrorHandler ist wird nach der Methode 2 erklärt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Methode 2 : OnIdle====&lt;br /&gt;
&lt;br /&gt;
OnIdle ist ein besonderes Ereignis, welches das gesamte Programm betrifft. Wenn die Anwendung nichts zu tun hat, also faul ist (engl. idle), tritt das Ereignis ein.&lt;br /&gt;
Die Methode mit OnIdle kann gleich mit zum Auswerten der Framezahlen (Anzahl Bildwiederholungen pro Sekunde) benutzt werden (Framecounter). Der nachfolgende Code enthält selbigen bereits.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;procedure TForm1.IdleHandler(Sender: TObject; var Done: Boolean);&lt;br /&gt;
begin&lt;br /&gt;
  StartTime:= GetTickCount;&lt;br /&gt;
  Render;&lt;br /&gt;
  DrawTime:= GetTickCount - StartTime;&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;
    TimeCount:= TimeCount - 1000;&lt;br /&gt;
    FrameCount:= 0;&lt;br /&gt;
    Caption:= InttoStr(Frames) + 'FPS';&lt;br /&gt;
    ErrorHandler;&lt;br /&gt;
  end;&lt;br /&gt;
&lt;br /&gt;
  Done:= false;&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Zeile 3:''' Mittels GetTickCount wird die Systemzeit gemessen. Dies ist nicht nötig um &lt;br /&gt;
erfolgreich zu zeichnen, sondern dient ausschließlich der Berechnung der Framerate. Diese wiederum ist ein guter Performancemesser.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 4:''' Hier erfolgt der Aufruf unserer Zeichenroutine.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 9:''' Der hier angeordnete Block wird nur pro Sekunde einmal ausgeführt und sorgt &lt;br /&gt;
dafür, dass die Framerate angezeigt wird. Außerdem wird der Errorhandler aufgerufen.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 14:''' Der Errorhandler wird im Anschluß beschrieben.&lt;br /&gt;
&lt;br /&gt;
'''Zeile 17:''' Wenn ''Done'' nach der Ausführung ''false'' ist und das Programm wieder nichts zu tun &lt;br /&gt;
hat, wird OnIdle erneut ausgeführt. Wenn ''Done = true'' ist wird OnIdle nur einmal ausgeführt.&lt;br /&gt;
&lt;br /&gt;
===Der ErrorHandler  Fehler erkannt, Fehler gebannt===&lt;br /&gt;
Der Errorhandler ist wieder eine total einfache Funktion, denn OpenGL bietet von Haus aus eine Möglichkeit OpenGL-Fehler zu erkennen. Deshalb ist der ErrorHandler auch so klein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pascal&amp;gt;procedure TForm1.ErrorHandler;&lt;br /&gt;
begin&lt;br /&gt;
  gluErrorString(glGetError);&lt;br /&gt;
end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enttäuscht? Ihr könnt den ErrorHandler nach belieben auch komplexer machen. Oder anstatt die Ausgabe anzuzeigen lieber den Fehler in ein Logfile schreiben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eure Klasse TForm1 sollte also jetzt so, oder so ähnlich aussehen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;TForm1 = class(TForm)&lt;br /&gt;
    procedure FormCreate(Sender: TObject);&lt;br /&gt;
    procedure IdleHandler(Sender: TObject; var Done: Boolean);&lt;br /&gt;
    procedure FormResize(Sender: TObject);&lt;br /&gt;
    procedure FormDestroy(Sender: TObject);&lt;br /&gt;
  private    { Private-Deklarationen }&lt;br /&gt;
    StartTime, TimeCount, FrameCount  : Cardinal; //FrameCounter&lt;br /&gt;
    Frames, DrawTime                  : Cardinal; //&amp;amp; Timebased Movement&lt;br /&gt;
    procedure SetupGL;&lt;br /&gt;
    procedure Init;&lt;br /&gt;
    procedure Render;&lt;br /&gt;
    procedure ErrorHandler;&lt;br /&gt;
  public    { Public-Deklarationen }&lt;br /&gt;
    DC                                : HDC;  //Handle auf Zeichenfläche&lt;br /&gt;
    RC                                : HGLRC;//Rendering Context&lt;br /&gt;
  end;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Zeile 3:''' Wie man sieht benutzt mein Template die zweite Methode (OnIdle).&lt;br /&gt;
&lt;br /&gt;
'''Zeile 8:''' Was [[Timebased Movement]] ist könnt ihr ja mal nachlesen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So....fertig. Eigentlich seid Ihr jetzt soweit von den Tutorialschreibern so richtig mit OpenGLWissen voll gepumpt zu werden. Das nachfolgende Kapitel könnt Ihr Euch trotzdem ruhigen Gewissens durchlesen. Wer es liest tappt vielleicht nicht gleich bei der ersten Frage im DGL-Forum ins berüchtigte Fettnäpfchen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Tipps für den OpenGL Anfänger==&lt;br /&gt;
Wenn man mit OpenGL anfängt ist man meist total perplex und ein &amp;quot;Das war ja einfach!&amp;quot; huscht einem nicht nur einmal über die Lippen. Vor allem zu Beginn Eurer OpenGL-Karriere werdet Ihr viel lernen und dabei nur auf verhältnismäßig geringen Widerstand stoßen. Aber glaubt mir es gibt ihn...&lt;br /&gt;
&lt;br /&gt;
Häufig tauchen hoch motivierte OpenGL Anfänger im Forum auf und verkünden stolz, sie würden gerade an einer Engine arbeiten die &amp;quot;nur auf Doom 1 Niveau arbeiten soll&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Dazu gibt es häufig eine durchaus beachtliche Anzahl von Forenmitgliedern die dann ungefähr folgendes sagen: Fang gar nicht erst damit an. Vergiss es, und komm in einem Jahr noch mal darauf zurück! (Die Forensuche sollte Euch einige dieser Threads zeigen)&lt;br /&gt;
&lt;br /&gt;
Sind das bösen Pessimisten, die Probleme nutzen um aufzugeben? '''Nein!''' Sie haben zumeist die Erfahrungen gemacht, die Ihr noch machen werdet. Deshalb will ich Euch an dieser Stelle einweihen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;1. Je älter der Code ist desto besser wird er.&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leider nein. Code und Wein unterscheiden sich hier leider grundlegend. Viele ... die meisten ... eigentlich alle von uns bekommen Ausschlag, wenn sie sich ihren Code von vor 1 Jahr angucken. Erst wenn man so schätzungsweise 3 bis 5 Jahre mit OpenGL gearbeitet hat, hat man ein echtes Gefühl für den Code. Am Anfang hat man nämlich, ob man will oder nicht, die Tendenz schon nach den ersten 3 Wochen Programmierarbeit sich den Code so zu zerschießen, dass die weitere Arbeit keinen Spaß mehr macht.&lt;br /&gt;
&lt;br /&gt;
''Ich selbst wollte jetzt ein Projekt weiterbearbeiten, welches ungefähr ein 3/4 Jahr alt ist... Ich hab den Code weggeworfen und das fast fertige Spiel neu angefangen. (Glaubt mir: Aus solchen Fehlern lernt man!)''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;2. Große Projekte = Großer Ruhm&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stimmt! ABER Ruhm gibt es in der Szene nur für beendete Projekte. Und dreimal dürft Ihr raten was durch die im Punkt 1 angesprochenen Probleme meist nicht mit euren Projekten passiert ... .&lt;br /&gt;
&lt;br /&gt;
Wenn Ihr OpenGL nur zur Visualisierung von z.B. wissenschaftlichen Ergebnissen benutzt, ist die Arbeit im Bezug auf OpenGL sehr übersichtlich. Wenn Ihr allerdings Spiele programmieren wollt, werdet Ihr schnell merken, dass Probleme auf Euch zukommen werden, die Euch beim Projektstart völlig unbekannt waren. Dies ist ein sicheres Zeichen dafür, dass doch noch etwas mehr Erfahrung nötig sein wird.&lt;br /&gt;
&lt;br /&gt;
'''Und woher soll ich bitte Erfahrung nehmen?'''&amp;lt;br&amp;gt;&lt;br /&gt;
Darin liegt der Trick: &amp;lt;br&amp;gt;&lt;br /&gt;
Alle OpenGLer haben einmal &amp;quot;klein&amp;quot; angefangen. Berühmt berüchtigt sind die 3DPong-Clone, die zahlreich im Internet anzufinden sind. Auch Tetris-, Memory- oder &amp;quot;Vier Gewinnt&amp;quot;-Clone sind solche stillen Zeugen eines großen Lernvorgangs. Das Besondere an solchen Spielen ist, dass die Spiellogik relativ einfach ist und Euch damit nur wenig von der Visualisierung ablenken. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ihr denkt jetzt bestimmt &amp;quot;Was kann man denn schon in so nem Clon unterbringen?&amp;quot; VERDAMMT VIEL! Hier mal ein kleiner Auszug:&lt;br /&gt;
&lt;br /&gt;
*3D-Spieldarstellung&lt;br /&gt;
*2D Menüführung ([[glOrtho]])&lt;br /&gt;
*[[Blending]] &lt;br /&gt;
*[[Textur]]en &lt;br /&gt;
*Licht und Materialien (Ihr werdet Augen machen!)&lt;br /&gt;
*[[Selektion]] (Hin und wieder zum Haare raufen.)&lt;br /&gt;
*Kamerasteuerung /Bewegung durch die Szene (Da gibt es ganze Tutorials dazu)&lt;br /&gt;
&lt;br /&gt;
Als Ansporn solltet Ihr Euch am Anfang ein kleines Ziel setzen und sagen &amp;quot;Ich möchte den besten und schönsten XYZ-Clon im ganzen Internet schaffen!&amp;quot;. So etwas trifft in der Szene auf wesentlich mehr Anerkennung als wenn mal wieder ein Anfänger etwas von Engine und Doom X faselt.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn Ihr ein oder zwei solcher Projekte abgeschlossen habt, und regelmäßig im Forum bzw. Wiki gelesen habt werdet Ihr schon merken, wenn Euer Traumprojekt endlich in Angriff genommen werden kann. (Ganz vergessen müsst ihr es nämlich doch nicht ;) )&lt;br /&gt;
&lt;br /&gt;
'''Als kurze Zusammenfassung solltet Ihr Euch merken:'''&lt;br /&gt;
&lt;br /&gt;
*Ein fertiges Projekt bringt Euch Ruhm (Seelenbalsam).&lt;br /&gt;
*Ein hübsches, fertiges Projekt bringt Euch mehr Ruhm.&lt;br /&gt;
*Ein großes, fertiges, hübsches Projekt bringt Euch noch mehr Ruhm.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Ein abgebrochenes oder eingefrorenes Projekt bringt Euch Frust.&lt;br /&gt;
*Ein großes, abgebrochenes Projekt bringt Euch noch mehr Frust, denn der verschwendeten Zeit werdet Ihr nachtrauern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;3.Das es lang dauert ist egal. Ich interessiere mich halt dafür.&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Aussage gilt nur dann, wenn Ihr schon über ein Jahr an ein und demselben Projekt gearbeitet habt. Anfänglich ist das kein Problem. Aber wenn man lange an etwas arbeitet und die gemachten Änderungen sind nicht sichtbar (weil sie z.B. den eigentlichen Motor der Anwendung betreffen und nicht die Ausgabe) dann verliert man schon mal die Lust. Folge sind die berüchtigten &amp;quot;Erfolgsmeldungen&amp;quot; wie: &amp;quot;Das Projekt wurde von mir bis auf weiteres aufs Eis gelegt. Ich werde sicherlich später daran weiterarbeiten.&amp;quot; In Verbindung mit Punkt 1 und den letzen Satz aus Punkt 2 sollte Euch das Endergebnis klar sein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Nachwort==&lt;br /&gt;
&lt;br /&gt;
Soviel zur Euphoriebremse. OpenGL ist toll. OpenGL ist die Lösung für Eure Traumanwendung. Aber die wird auch mit OpenGL nicht von heute auf morgen programmiert. Deshalb heißt es Tutorials lesen kleine Testanwendungen schreiben um Effekte zu testen und Projekte bearbeiten. Dann wird es auch etwas mit den Traumprojekten. Zudem kann man anfangs auch versuchen in sehr kleinen Anwendungen einen Effekt auszuprobieren und diesen in Form eines kleinen Beispielprogramms oder eines Tutorials zu veröffenlichen. Somit lernt man nicht nur selbst etwas dazu...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach diesen unglaublich Weise klingenden Worten die ich mit einem hoch ernsten Gesicht geschrieben habe, könnt ihr euch jetzt hochmotiviert an die restlichen Tutorials machen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bis bald im [http://delphiGL.com/forum Forum]&amp;lt;br&amp;gt;&lt;br /&gt;
'''Euer''' &amp;lt;br&amp;gt;&lt;br /&gt;
'''Flash (Kevin Fleischer)'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
PS: Feedback wird nicht nur gewünscht, sondern ausdrücklich gefordert. Deshalb: Ab mit deinen Meinungen und Ratschläge ins [http://www.delphigl.com/forum/viewforum.php?f=8 Feedback-Forum]!&lt;br /&gt;
&lt;br /&gt;
{{TUTORIAL_NAVIGATION|-|[[Tutorial_lektion1]]}}&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_3&amp;diff=8962</id>
		<title>Tutorial Lektion 3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_3&amp;diff=8962"/>
				<updated>2005-05-03T20:14:43Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: glOrtho2D-&amp;gt;gluOrtho2D&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Eine Welt des Grauens =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Liebe Leser,&lt;br /&gt;
nachdem Ihr hoffentlich den kleinen Schock des letzten Tutorials alle gut überstanden habt, freue ich mich, Euch hier wieder begrüßen zu können. Wer dachte, dass die letzte Lektion bereits schwer war, der sollte dringend Urlaub nehmen. Seid gewarnt! Bevor ich jetzt richtig loslege, solltet Ihr einigermaßen entspannt sein. Wenn dies einer der Tage ist, an denen Ihr nur noch durch eine Kippe oder die Flasche Coke am Leben gehalten werdet, ordne ich erstmal eine kleine Zwangspause an ;).&lt;br /&gt;
&lt;br /&gt;
Der Stoff der jetzt kommt ist sicherlich nicht gerade die leichteste Lektüre. Wer Mathematik studiert, hat Vorteile, wer einigermaßen logisch denken kann auch. Ein Fachidiot, wie ich, hat nur eine Chance probieren, testen und lernen :). Und weil ich weiß, wie schwer es eventuell sein kann, werde ich nun einfach mal versuchen, ganz simpel anzufangen und das Ganze mit vielen Bildern so gut wie nur irgend möglich zu illustrieren. &lt;br /&gt;
&lt;br /&gt;
Und wenn Ihr nun Angst habt, dass Ihr das nicht packt, weil ich hier so eine Panik verbreite, dann solltet Ihr mich sehen, wie ich hier verzweifelt vor meinen Tasten hänge und mich frage, wie ich das alles bloß in Worte fassen soll :). Aber was soll es? Ran an den Kram!!! Heulen könnt Ihr anschließend im Forum ;).&lt;br /&gt;
== Das Grauen hat einen Namen ==&lt;br /&gt;
=== &amp;quot;Kinofilm&amp;quot; vs. &amp;quot;Bahnhof&amp;quot; ===&lt;br /&gt;
Wer kennt nicht &amp;quot;Matrix&amp;quot; und hätte gedacht, dass es davon nicht nur eine, sondern unendlich viele gibt die so genannten &amp;quot;Matrizen&amp;quot;. Vor allem am Anfang werden diese Dinger Euch das Leben erschweren und Ihr werdet leichte Neigungen tief in Euch verspüren, dass am besten Euer ganzes Projekt sich nur im Zentrum Eurer Welt abspielt (und dies ist nicht im wahrsten Sinne des Wortes gemeint).&lt;br /&gt;
&lt;br /&gt;
Wer mit Matrizen umgehen kann, beherrscht das Wichtigste an der 3D-Programmierung. Wer nicht zu den Genies zählt, sollte nicht sofort aufgeben, sondern sich viele Beispiele ansehen und viel mit diesen herumspielen.&lt;br /&gt;
&lt;br /&gt;
Wie auch immer Ihr solltest wissen, dass es bei jedem Rendervorgang mehrere Matrizen gibt, die ganz drastisch das Aussehen der Szene bestimmen. Es gibt in OpenGL drei Bereiche, in denen Matrizen eingesetzt werden. Die so genannte World- oder Modelviewmatrix, die Texturenmatrix und die Perspektivenmatrix. Die zweifellos wichtigste dieser Matrizen ist die Worldmatrix, da sie die Position Eures Zeichenstiftes beschreibt und somit Objekte positioniert. Die Texturenmatrix funktioniert fast genauso wie die Worldmatrix nur definiert sie die Ausrichtung der Texturen. Wir werden später auf sie zurückkommen. Die Perspektivenmatrix definiert wesentliche Eigenschaften des Blickfeldes des Betrachters.&lt;br /&gt;
&lt;br /&gt;
Der Befehl [[glMatrixMode]] erlaubt eine Änderung der aktuellen Matrix. Mit Hilfe der Konstanten GL_MODELVIEW, GL_TEXTURE oder GL_PERSPECTIVE kann man die Matrix bestimmen. Die Namen der Konstanten sind soweit hoffentlich selbst erklärend. Von nun an bewirken alle Matrixoperationen wie beispielsweise [[glLoadIdentity]] oder [[glTranslate|glTranslate*]] eine Veränderung der aktuell gesetzten Matrix.&lt;br /&gt;
=== Die Perspektivenmatrix ===&lt;br /&gt;
Wie bereits erwähnt beschreibt die Perspektivenmatrix das aktuelle Sichtfeld. Zum Setzen der Perspektivenmatrix verwendet man in der Regel Befehle wie [[glFrustum]], [[gluPerspective]], [[glOrtho]] oder [[gluOrtho2D]].&lt;br /&gt;
&lt;br /&gt;
gluPerspective lässt den Raum beispielsweise dreidimensional erscheinen, indem sich die Größe von Objekten mit zunehmender Entfernung vom Betrachter verringert. Diese Verringerung ist abhängig von dem im ersten Parameter übergebenen Winkel. &lt;br /&gt;
&lt;br /&gt;
glOrtho hingegen ist phantastisch für ein 2D-Blickfeld geeignet, denn diese Art der Projektion enthält keine Tiefe mehr.&lt;br /&gt;
&lt;br /&gt;
Genauere Informationen zu den einzelnen Funktionen könnt ihr unserem OpenGL-Wiki entnehmen.&lt;br /&gt;
&lt;br /&gt;
Auf eine Sache möchte ich jedoch noch eingehen: Einige dieser Funktionen verlangen die Parameter znear und zfar. Diese Parameter beschreiben die zwei Schnittflächen, die das Blickfeld vor dem Betrachter begrenzen. &amp;quot;znear definiert die Entfernung der Nearclippingplane vom Betrachter. Alle Objekte, die sich vor dieser Ebene befinden sind nicht sichtbar. zfar beschreibt die Entfernung der Farclippingplane vom Betrachter. Alle Objekte, die sich hinter dieser befinden werden weggeschnitten. Wenn also wieder einmal nur die Hälfte Eurer Szene auf dem Bildschirm sichtbar ist, versucht die Schnittflächen entsprechend anzupassen!&lt;br /&gt;
&lt;br /&gt;
== Die Worldmatrix ==&lt;br /&gt;
=== D3D-Verrat ===&lt;br /&gt;
Wenn Ihr ebenfalls zu den D3D-Verrätern gehört (wie z.B. ich *g*), dann solltet Ihr Euch möglichst von eurer Denkweise trennen: Jede Positionierung der Kamera erfolgt über ein Drehen und Bewegen der Szene. Das ist vor allem am Anfang ein wenig gewöhnungsbedürftig (&amp;quot;Die Welt dreht sich! Nicht Du!&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Vielmehr wird jede Manipulation direkt an die Worldmatrix übergeben. Das heißt, wenn Ihr glTranslate* aufruft, so ist diese Manipulation bereits bei Euch in die Worldmatrix eingetragen, alle weiteren Objekte werden mit dieser Matrix transformiert. Wer zweimal glTranslate*(2, 0, 0) aufruft wird feststellen, dass glTranslate* nicht zwei Matrizen zurückliefert, sondern nur eine, die dann auf (4, 0, 0) verweist. Am Anfang solltet Ihr also sehr darauf achten, es wird eine Weile dauern bis Ihr dies fest in Eurem Herzen tragt. Nicht sofort aufgeben :)!&lt;br /&gt;
== Einfach, Kompakt und Funktional ==&lt;br /&gt;
Neben dem Befehl glTranslate*, den wir im letzten Tutorial lieben gelernt haben, gibt es noch weitere Befehle, die sich auf die einzelnen Matrizen auswirken und auf die ich in dem folgenden Abschnitt eingehen möchte.&lt;br /&gt;
=== Dreh- und Angelpunkt des Geschehens ===&lt;br /&gt;
Zunächst beschäftigen wir uns mit der Rotation. Wir versuchen ein Objekt zu erzeugen, welches um 90° um seine eigene Achse gedreht wurde. Das ist nicht sonderlich schwer: &amp;lt;pascal&amp;gt;[[glRotate|glRotatef]](90,0,1,0);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Ein Objekt auf das wir diese Matrix anwenden, wird um 90° um seine Y-Achse gedreht sein. Daraus schließen wir, dass der erste Parameter den Winkel im Gradmaß um den wir rotieren möchten definiert und die 3 folgenden Parameter den Vektor beschreiben um den die Rotation durchgeführt werden soll. Rotationen bergen tatsächlich eine Schwierigkeit, denn es ist nicht immer einfach ein Objekt um die Eigene Achse zu rotieren. Verschiebt Ihr euer Objekt zuerst und beginnt dann die Rotation, so rotiert das Objekt um die eigene Achse.&lt;br /&gt;
&lt;br /&gt;
Ruft Ihr jedoch zuerst glRotate* und anschließend glTranslate* auf, so unterscheidet sich erzielte Ergebnis von dem vorherigen.&lt;br /&gt;
&lt;br /&gt;
Um diesen Problemen aus dem Weg zu gehen so müsst Ihr Euch vorstellen, dass Ihr den Rotationspunkt im Moment des Aufrufs von glRotate* setzt. Verschiebt Ihr Euer Objekt anschließend so bleibt der Rotationspunkt derselbe und das Objekt beginnt den Rotationspunkt auf einer Bahn zu umkreisen. So gesehen gibt es keinen wirklichen Unterschied und die Rotation um die eigene Achse ist ein Ausnahmefall, denn der Rotationspunkt liegt dann in dem von uns erwarteten Mittelpunkt des Objektes.&lt;br /&gt;
=== Eine Frage der Größe ===&lt;br /&gt;
Nun ja was kann man denn noch alles in einer 3D-Welt machen? Ihr habt gelernt, wie man Objekte bewegt und diese durch Rotationen ausrichten kann. Das ist doch schon eine Menge zum Spielen oder? Nun, bei einer Transformation kann für uns noch eine Sache sehr wichtig werden, nämlich die Möglichkeit, zu bestimmen in welcher Größe ein Objekt dargestellt werden kann.&lt;br /&gt;
&lt;br /&gt;
Sicher würde es Sinn machen ein benötigtes Objekt gleich in der richtigen Größe in die Anwendung zu laden. Manchmal ist es aber von Vorteil, wenn man die Größe eines Objektes ohne großen Aufwand verändern kann oder aber mehrere Objekte desselben Typs mit unterschiedlicher Größe darzustellen.&lt;br /&gt;
&lt;br /&gt;
Eine Größenveränderung ist mit Hilfe des Befehls [[glScale|glScale*]] möglich.&lt;br /&gt;
&amp;lt;pascal&amp;gt;glScalef(1,1,1);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
In diesem Fall würden wir das Objekt so zeichnen, wie wir es auch angegeben haben. Das heißt in seiner Originalgröße. Sicherlich ahnst Du bereits, was die Parameter aussagen sie stehen für das Verhältnis der einzelnen Seiten nach dem Muster X, Y und Z. Würden wir als ersten Parameter statt einer 1 eine 2 einsetzen, würde unser Objekt in seiner räumlichen Ausdehnung bezogen auf der X-Achse doppelt so groß sein. Würden wir stattdessen 0.5 angeben, wäre es nur noch halb so groß.&lt;br /&gt;
&lt;br /&gt;
In Wirklichkeit bewirkt glScale* jedoch keine Veränderung der Größe sondern eine Verzerrung unseres Koordinatensystems. Daher wirkt jeder Aufruf von glScale* auch auf Befehle wie glTranslate*. Aus Sicht der Matrizen lässt sich dieses Phänomen auch recht leicht erklären. In Wirklichkeit erzeugt jeder Aufruf von glRotate*, glTranslate* oder glScale* eine eigene Matrix, die dann mit der aktuellen Matrix (z.B. der Modelviewmatrix) multipliziert wird. Wurde in der Modelviewmatrix bereits ein glScale* verewigt, so wirkt sich dieses bei der Multiplikation der Matrizen auf die Transformationsmatrix aus.&lt;br /&gt;
&lt;br /&gt;
Ich denke ich muss nicht näher darauf eingehen, dass es keine gute Idee ist das Koordinatensystem mit einem Aufruf von glScalef(0, 0, 0) zu zerstören. Was würde es auch für einen Sinn ergeben, das Koordinatensystem in einem Punkt unterzubringen? &lt;br /&gt;
&lt;br /&gt;
Ich hoffe ich habe Euch nun nicht den letzten Funken Hoffnung OpenGL zu verstehen geraubt. Ich kann Euch versichern, dass dieses Verständnis mit der Zeit heranreifen wird.&lt;br /&gt;
[[bild:tutimg_lektion3_skalierung.gif|256px|right]]&lt;br /&gt;
glScale* ist aber aufgrund seiner phantastischen Eigenschaften nicht nur in der Lage die Größe von Objekten zu verändern sondern es ist auch möglich Objekte zu spiegeln indem man negative Werte an glScale* übergibt. Somit kann sich z.B. ein D3D-Umsteiger das leben vereinfachen indem er mit einem Aufruf von glScalef(1, 1, -1) sicherstellt, dass die Z-Achse in den Bildschirm hinein positiv verläuft.&lt;br /&gt;
&lt;br /&gt;
Jeder, der die Funktion der Modelviewmatrix begreifen möchte, dem möchte ich das Programm Matrixcontrol von Lithander (siehe Anhang) ans Herz legen. Es erlaubt Euch bestimmte Änderungen an der Matrix direkt nachzuvollziehen und wenn man mit dem Programm ein wenig umherspielt wird selbst dem letzten ziemlich schnell ein Licht aufgehen. Wenn nicht, dann hilft nur fleißiges Programmieren und Anwenden und irgendwann klatscht es dann laut, wenn die eigene Handfläche auf der Stirn zum stehen kommt ;).&lt;br /&gt;
== Virtuelle Gedächtnisse ==&lt;br /&gt;
=== Vom Pushen und Poppen ===&lt;br /&gt;
Wer diesen Titel ließt und sich nun zwangsläufig daran erinnert, was er bereits alles in seinem Leben konsumiert hat oder neben wenn er am nächsten Morgen aufgewacht ist, sei entwarnt! Wir reden hier von etwas ganz anderem&lt;br /&gt;
&lt;br /&gt;
Wie wir bereits gelernt haben, verändert jeder Aufruf von glTranslate*, glRotate* oder glScale* die Worldmatrix und wirkt sich unmittelbar auf andere Objekte aus. Dies kann durchaus sehr erwünscht sein. Wenn wir allerdings in einer großen Welt verschiedene Objekte positionieren, kann dies schnell zum Fluch werden. Natürlich können wir dem entgegenwirken und zum Beispiel jedes Mal glLoadIdentity aufrufen. Dies hat jedoch den Nachteil, dass die World- Matrix dann eben wieder leer ist und wir z.B. die Camera erst wieder setzen müssen, damit die Objekte an die richtige Stelle transformiert werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitaus elegantere Lösung ist die Verwendung des &amp;quot;Matrixstacks&amp;quot;! Jeder Aufruf von [[glPushMatrix]] bewirkt, dass die momentane Matrix auf den Stack geschrieben wird. Alle Manipulationen, die wir dann durchführen, werden wie gewohnt vollzogen. Ist alles gezeichnet, rufen wir mit [[glPopMatrix]], die letzte Matrix vom Stack wieder herunter und haben im Prinzip den letzten Zustand vor unseren Veränderungen rekonstruiert und können dann wieder anfangen, auf dieser Matrix aufzubauen. Natürlich lassen sich auch mehre Matrizen auf den Stack pushen! Dies kann reichlich Zeit sparen, wenn man bedenkt, dass man ansonsten andauernd die Matrix der Szene neu setzen muss.&lt;br /&gt;
&lt;br /&gt;
Um das ganze etwas anschaulicher zu machen, verwenden wir ein einfaches Beispiel. Wir werden zwei Dreiecke jeweils rechts und links vom Ursprung zeichnen. Nachdem wir das linke Objekt gezeichnet haben, werden wir nicht glLoadIdentity einsetzen oder das zweite Objekt entsprechend nach rechts transformieren, sondern eben den Matrixstack zu Hilfe nehmen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;glLoadIdentity;&lt;br /&gt;
glTranslatef(0,0,-10);&lt;br /&gt;
glPushMatrix;&lt;br /&gt;
  glTranslatef(-2,0,0);&lt;br /&gt;
  glBegin(GL_TRIANGLES);&lt;br /&gt;
    glColor3f(1,0,0); glVertex3f(-1,-1, 0);&lt;br /&gt;
    glColor3f(0,1,0); glVertex3f( 0, 1, 0);&lt;br /&gt;
    glColor3f(0,0,1); glVertex3f( 1,-1, 0);&lt;br /&gt;
  glEnd;&lt;br /&gt;
glPopMatrix;&lt;br /&gt;
&lt;br /&gt;
glTranslatef(2,0,0);&lt;br /&gt;
glBegin(GL_TRIANGLES);&lt;br /&gt;
  glColor3f(1,0,0); glVertex3f(-1,-1, 0);&lt;br /&gt;
  glColor3f(0,1,0); glVertex3f( 0, 1, 0);&lt;br /&gt;
  glColor3f(0,0,1); glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wie Ihr seht, setzen wir am Anfang praktisch die Distanz zum Objekt, speichern die Matrix und zeichnen das erste Objekt. Wir setzen dann die Matrix wieder zurück, so dass sie nur noch den Aufruf von glTranslatef(0, 0, -10) beschreibt und transformieren das zweite Objekt fertig. Man kann auch ohne diese Matrixstacks leben sie können einem aber das Leben auch sehr erleichtern.&lt;br /&gt;
== I wanna all! ==&lt;br /&gt;
Wer glaubt, dass es das bereits war der irrt. Es gibt noch weitere Möglichkeiten auf die Matrix Einfluss zu nehmen. Der Befehl [[glLoadMatrix|glLoadMatrix*]] erlaubt es eine beliebige 4x4 Matrix zu laden und die aktuelle Matrix durch die geladene komplett zu ersetzen.&lt;br /&gt;
&lt;br /&gt;
Der Befehl [[glMultMatrix|glMultMatrix*]] multipliziert die übergebene 4x4-Matrix mit der aktuellen Matrix. Mit diesem Befehl könnte man beispielsweise eigene glScale*- und glRotate*-Befehle schreiben, obgleich sich auch hier über den Sinn streiten lässt. Eine sinnvollere Anwendungsmöglichkeit wird in einem späteren Tutorial vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Befehl [[glGet|glGet*]] mit den Tokens GL_MODELVIEW_MATRIX, GL_TEXTURE_MATRIX und GL_PROJECTION_MATRIX ermöglicht euch die einzelnen Matrizen anzufordern.&lt;br /&gt;
== Weltenformeln ==&lt;br /&gt;
=== Hier kommt die Sonne ===&lt;br /&gt;
Genug der Theorie! Es wird langsam Zeit für etwas Praxis&lt;br /&gt;
&lt;br /&gt;
Nun, um ehrlich zu sein, habe ich an der folgenden Idee ein wenig Zeit benötigt, um ein einigermaßen gut anschauliches Beispiel zu finden ich will hier nicht weiter darauf eingehen, was ich gerade gehört habe, als mir die Sonne aufging :-D.&lt;br /&gt;
&lt;br /&gt;
Wie auch immer, man kann komplexere Matrixtransformationen sehr leicht mit unseren Sonnensystem beschreiben (Hey, wenn jetzt jemand denkt, dass ich spinne). Um das Ganze etwas übersichtlicher zu gestalten, werden wir unser Prinzip auf Sonne, Mond und Erde beschränken.&lt;br /&gt;
&lt;br /&gt;
Wie funktioniert unser Sonnensystem? (Warnung, der Autor betritt mal wieder seine ausgeprägte Fantasywelt! [Anm. d. Lektors: Die richtige Sprache dafür hat er ja schon]).&lt;br /&gt;
&lt;br /&gt;
Die Sonne steht im Mittelpunkt und sollte sich in unserem Beispiel nicht selbst bewegen. Sie ist einfach nur im Mittelpunkt und vegetiert dort vor sich hin! Nun gibt es einen kleinen blauen Planeten, namens Erde (wieso er im Sample ein Dreieck ist, sei Eurer Kreativität überlassen), der zum einen um seine eigene Achse rotiert, viel wichtiger jedoch, sich auch noch um die Sonne dreht. Nun werden sich vor allem die Neulinge unter Euch sadistisch freuen, das Fenster schließen, ihr Delphi starten und drauf los proggen! Das ist doch alles kein Ding, der gerade mal frisch aufgeschnappte Sinus-Satz lässt sich prima mit einbringen! Und schon berechnet man mit Hilfe von Sinus, die Position auf der Kreisbahn und positioniert den Planeten mit glTranslate* an seine Position. Und oh Wunder es klappt. HALT! Wer es nicht gemerkt hat, da war ne Portion Ironie dabei. Bitte Weiterlesen ^__ ^!&lt;br /&gt;
&lt;br /&gt;
Denn spätestens wenn wir folgende Ergänzung zum Besten geben, werden die ersten Augen wässrig werden, weil die meisten Hirne einem Informationskoller unterliegen. Meines stieg ja schon beim einfachen Sinus aus :-D. Ab und an kann man nämlich nachts weißgräuliche Flecken am Himmel beobachten! Wer annimmt, dass es sich hierbei um eine geschickt platzierte, in Echtzeit berechnete, Textur handelt, ist schief gewickelt! Es handelt sich dabei nämlich um ein Decal, namens Mond. Oha so schlimm war es schon lange nicht mehr. Dieser bewegt sich in unserem Beispiel auch nicht entlang der Erdachse, sondern auf einer schiefen Bahn, damit man auf der unteren Hemissphäre den Mond auch am Tage noch sehen kann ^___^ (*selbstgefälliges, göttliches Grinsen*). Dies lässt sich nur sehr schwer mit Sinus beschreiben. Bevor wir uns nun jedoch mit einem Block bewaffnen oder den nächsten Mathematik-Professor entführen, damit er die Mathematik für uns übernimmt, greifen wir lieber zu den Sternen und nehmen ein einfacheres Verfahren! Les Matrices!&lt;br /&gt;
=== Und es dreht sich doch! ===&lt;br /&gt;
Die Vorgehensweise ist eigentlich relativ simpel. Wir Zeichnen unsere Sonne im Mittelpunkt unseres Universums. Mit dem Aufruf von glRotate* setzen wir den Rotationspunkt an die Position unseres Zeichenstiftes. In unserem Fall ist das noch immer die Position der Sonne. &lt;br /&gt;
&lt;br /&gt;
Nun verschieben wir die Erde nach links und die erste Hürde ist genommen. Jetzt müssen wir nur noch den Mond setzen und das funktioniert genauso einfach wie zuvor mit der Erde.&lt;br /&gt;
&lt;br /&gt;
Unser Zeichenstift befindet sich nun an der Position der Erde und daher rufen wir glRotate* auf. Nun müssen wir den Zeichenstift nur noch ein kleines Stück neben der Erde positionieren und den Mond zeichnen. Voila! Es ist vollbracht!&lt;br /&gt;
&lt;br /&gt;
Wenn man genauer darüber nachdenkt erkennt man sehr schnell wie elegant man dieses verhältnismäßig komplizierte Problem gelöst hat.&lt;br /&gt;
&lt;br /&gt;
Wer nun auf Wolke Sieben schwebt und glaubt er könnte sich nun an den nächsten DOOMTitel werfen, der sollte das Programm zuvor noch so erweitern, dass die Sonne, die Erde und auch der Mond sich zusätzlich um die eigene Achse drehen.&lt;br /&gt;
== Timebased Movement ==&lt;br /&gt;
Wer bereits versucht hat eines der ersten selbst geschriebenen OpenGL-Programme voller Stolz seinem Kumpel vorzuführen wird festgestellt haben, dass die Bewegungen auf dem anderen Rechner schneller oder langsamer abgelaufen sind als es auf dem eigenen Rechner der Fall war.&lt;br /&gt;
&lt;br /&gt;
Dieses Phänomen lässt sich sehr einfach erklären. Nehmen wir an wir bewegen ein Dreieck von links nach rechts um den Wert 1 über den Bildschirm. Eine alte Krücke wie mein PC schafft vielleicht 50 FPS. Das bedeutet das Objekt wird in einer Sekunde genau 50mal um eine Einheit nach rechts verschoben. Das bedeutet insgesamt also um 50 Einheiten in einer Sekunde. Wenn das Programm nun aber auf einem High-End-System läuft werden wir die Szene sagen wir 500mal aktualisieren können. Folglich bewegt sich auf diesem Rechner das Dreieck in einer Sekunde um 500 Einheiten.&lt;br /&gt;
&lt;br /&gt;
Das einzige was wir von unserem Dreieck erhaschen können ist ein blitzartiges Zucken auf dem Bildschirm, welches wir schnell als optische Täuschung abtun würden. Wie kann man diesem Problem nun aber entgegen wirken?&lt;br /&gt;
&lt;br /&gt;
Nehmen wir an wir kennen die Zeit, die wir zum Zeichnen eines Frames benötigen und ermitteln anhand dieses Wertes einen Zeitfaktor, den wir in die Bewegung mit einfließen lassen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;NewPosition := OldPosition + Movement * TimeFactor;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Handelt es sich um einen schnellen Rechner so ist der Zeitfaktor entsprechend niedrig und die Bewegung pro Frame verringert sich. Ist der Rechner hingegen langsam so besitzen wir einen hohen Zeitfaktor. Folglich legt das Dreieck auf dem schnelleren Rechner pro Frame weniger Weg zurück als auf dem langsamen. Insgesamt jedoch legen die beiden Dreiecke im gleichen Zeitabstand (z.B. in einer Sekunde) denselben Weg zurück.&lt;br /&gt;
&lt;br /&gt;
Um den Zeitfaktor zu ermitteln muss man lediglich die Zeit für einen Schleifendurchlauf ermitteln. Um eine möglichst hohe Genauigkeit zu erhalten sollte man die Zeit für den letzten Schleifendurchlauf ermitteln und im aktuellen Schleifendurchlauf verwenden.&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Wow und wieder ein wenig Zeit zum Ausspannen und ein paar persönlichen Worten. Ich kann getrost nur eines sagen: Wenn Ihr nun denkt &amp;quot;das war alles ja sehr leicht&amp;quot; habt Ihr irgendetwas falsch gemacht und solltet das Tutorial noch einmal von Vorn durcharbeiten ;). Wenn Ihr jedoch leichte Kopfschmerzen verspürt (ob es nun die Matrizen sind oder der fiese Elementarbereich *sg*) so habt Ihr alles richtig gemacht ;).&lt;br /&gt;
&lt;br /&gt;
Matrizen sind vor allem vielen Einsteigern sehr fremd. &amp;quot;Übung macht den Meister&amp;quot;. Versucht Euch doch einfach mal die eine oder andere Aufgabe selbst zu stellen oder unser &amp;quot;Sonnensystem&amp;quot; selbst einmal nachzuschreiben. Wenn Ihr glaubt, dass das Ganze ganz nett geworden ist, dann schickt es mir doch einfach mal zu. Ich freue mich immer darüber zu sehen, was für Früchte meine Tutorials tragen. *lach* Und wenn sich plötzlich alles um die Erde dreht, dann habe ich a) das Gefühl, dass die Kenntnisse über das Sonnensystem nicht mehr ganz up to date sind oder b) ich einen ziemlich fatalen Fehler beim Erklären gemacht habe :-&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Schreckt auch bitte nicht davor zurück, eine Frage diesbezüglich im Forum zu stellen. Es ist keine Schande, mit einer Matrix Probleme zu haben und vor allem die Erfahrenen unter uns, sollten nur zu gut wissen, was alles die Ursache dafür sein kann, wenn man plötzlich gar nichts mehr auf dem Screen sieht :).&lt;br /&gt;
&lt;br /&gt;
Wir selbst werden uns in den folgenden Kapiteln noch etwas intensiver mit den Matrizen beschäftigen und unter anderem die eine oder andere interessante Spielerei zeigen!&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Anhang ==&lt;br /&gt;
&lt;br /&gt;
[http://www.pixelpracht.net Pixelpracht] -  Hier könnt Ihr das Programm Matrix Control finden&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=7492</id>
		<title>Tutorial Lektion 2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=7492"/>
				<updated>2005-05-02T19:02:30Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Entdeckung einer neuen Welt =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Ich möchte Euch an dieser Stelle bei DGL herzlich willkommen heißen. Vermutlich wird dies eines der ersten Tutorials sein, das Ihr als Einsteiger lesen werdet. Wahrscheinlich werdet Ihr dann auch noch nicht lange bei uns sein und Euch nicht vorstellen können, dass all die Schreiber auf unserer Seite keine Gurus, sondern ganz normale Menschen sind.&lt;br /&gt;
&lt;br /&gt;
Man kann uns also jeder Zeit im Forum anfassen, uns Fragen stellen, Vorschläge unterbreiten oder einfach nur einmal kurz mit einem Lob ermutigen weitere Texte zu verfassen ;-).&lt;br /&gt;
&lt;br /&gt;
Ich wünsche Euch an dieser Stelle viel Erfolg bei dem Einstieg in die Thematik OpenGL und ermahne Euch noch einmal, dass Ihr Eure Ziele nicht zu weit steckt. Wirklich Spaß beginnt OpenGL nämlich erst dann zu machen, wenn man stets kleinere Erfolge feiern kann.&lt;br /&gt;
== Höhere Mächte - Matrizen und ihre Folgen ==&lt;br /&gt;
=== Saubere Arbeit ===&lt;br /&gt;
Bevor wir direkt beginnen etwas zu Zeichnen müssen wir erst einmal das Bild löschen, denn wie in der vorherigen Lektion beschrieben zeichnen wir die Szene jeden Schleifendurchlauf neu. Das Löschen der Puffer, in dem die Bildinformationen enthalten sind übernimmt die Funktion [[glClear]]. Die Farbinformationen unser  [[Fragment|Fragmente]] (Fragmente sind vergleichbar mit den [[Pixel|Pixeln]] auf dem Bildschirm besitzen aber weitere Informationen wie z.B. Tiefenwerte. Bei der Ausgabe des Bildes werden diese Fragmente in Pixel umgewandelt) sind in dem so genannten [[Farbpuffer]] (Colorbuffer) gespeichert. Aus diesem Grund übergeben wir an die Funktion glClear die Konstante GL_COLOR_BUFFER_BIT.&lt;br /&gt;
&amp;lt;pascal&amp;gt;//Farbbuffer entleeren&lt;br /&gt;
glClear(GL_COLOR_BUFFER_BIT);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
[[bild:tutimg_lektion2_puffereffekt.gif|right]]&lt;br /&gt;
Mit Hilfe des Befehls [[glClearColor]] können wir festlegen, welche Farbinformationen mit dem Aufruf von glClear in den Colorbuffer geschrieben werden sollen. Wenn wir es also genau nehmen so löscht glClear den Colorbuffer nicht, sondern es schreibt ihn mit den definierten Werten voll. Standardmäßig erhalten die Fragmente eine schwarze Farbe.&lt;br /&gt;
&lt;br /&gt;
Es wird also nicht bei jedem Zeichenvorgang (Rendervorgang) der Bildspeicher gelöscht, sondern der Programmierer entscheidet, wann dies geschehen soll. Theoretisch könnt Ihr auch die Szene wiedergeben und dann löschen, bevor sie ausgegeben wird... wer's mag :).&lt;br /&gt;
&lt;br /&gt;
Wer sich entscheidet den Colorbuffer nicht zu löschen, der kann so auch einige nette Effekte erzeugen. Den Cheatern unter euch sollte der erreichte Effekt bekannt vorkommen, wenn man beispielsweise bei Counter-Strike durch die Wand gelaufen ist. Der Grund für das Verwischen ist in beiden Fällen derselbe: Das neue Bild wird gezeichnet, ohne dass das alte Bild aus dem Puffer entfernt wurde.&lt;br /&gt;
=== Und die Welt ist doch keine Scheibe ===&lt;br /&gt;
[[bild:tutimg_lektion2_koordinatensystem.gif|256px|right]]&lt;br /&gt;
Nachdem wir nun wieder Ordnung im Speicher geschafft haben, können wir zum interessanten Teil kommen: &amp;quot;Wie darf man sich einen 3D-Raum vorstellen?&amp;quot; Nun  warum schaut Ihr Euch nicht einmal in Eurem Zimmer um?&lt;br /&gt;
&lt;br /&gt;
Versuchen wir doch mal, ein Beispiel direkt aus dem Leben gegriffen zu nehmen und stellen uns unsere Umgebung als Koordinaten-System vor (Igitt!). Der Monitor, der hoffentlich direkt vor uns steht, ist in diesem Fall unser Ursprung, d.h. er liegt an dem Punkt (0, 0, 0).&lt;br /&gt;
&lt;br /&gt;
Blicken wir seitwärts neben den Monitor, so sehen wir eine Linie (wenn Ihr es nicht tun solltest, macht Euch keine Sorgen  solche Anfälle hat der Autor häufiger *g*), die von links nach rechts verläuft. Es handelt sich hierbei um die X-Achse, die links vom Monitor im negativen Bereich verläuft, rechts davon in den positiven.&lt;br /&gt;
&lt;br /&gt;
Nun blicken wir einmal nach oben und einmal nach unten und schon erspähen wir die Y-Achse, die oberhalb des Monitors positiv verläuft, unterhalb negativ. Wunderbar! Wenn Ihr bereits in 2D gearbeitet habt, solltet Ihr an dieser Stelle ein dümmliches Grinsen auf Eurem Gesichte haben und das wohltuenden Gefühl, dass Euch das doch alles bereits irgendwie bekannt vorkommt. Doch zu unserem Entsetzen können wir uns ja auch noch von unserem Bildschirm wegbewegen oder auch dichter heran (alle Kurzsichtigen unter uns sollten das nicht so persönlich nehmen, auch Sie leben in einem 3D-Raum ^__-).&lt;br /&gt;
&lt;br /&gt;
Dieses Phänomen ist im 3D-Raum typisch, jedoch nicht unerklärlich, da wir uns auf der Z-Achse bewegen. Rollen wir mit dem Stuhl vom Monitor weg, so gelangen wir in den positiven Bereich der Z-Achse, bewegen wir uns drauf zu, gelangen wir in den negativen Bereich. Jeder, der bereits in D3D programmiert hat, sollte sich schleunigst einprägen, dass das ein großer Unterschied zwischen D3D und OpenGL ist. Das kann sonst zu einigen wirklich fiesen Fehlern führen, wenn man es nicht weiß *fg*.&lt;br /&gt;
&lt;br /&gt;
Soweit so gut! Klingt bisher hoffentlich immer noch nicht so kompliziert. Nur keine Sorge, das Niveau versuchen wir zu halten ;).&lt;br /&gt;
&lt;br /&gt;
Speziell wenn Ihr bereits 2D-Spiele programmiert habt, solltet Ihr Euch sehr schnell von folgenden Gedanken trennen: Die Koordinaten, die Ihr seht und angebt, entsprechen in der Regel nicht den Pixeln des Bildschirmes, sondern so genannten Weltkoordinaten. Eine Definition für diese Weltkoordinaten gibt es nicht, denn wie groß diese sind ist dem Programmierer überlassen. Ob Ihr euer Objekt eine Einheit vor Euch und 0,1 Einheit rechts von Euch oder aber 100 Einheiten vor euch und 10 Einheiten neben Euch positioniert ist egal. Die euch zur Verfügung stehende Welt ist grenzenlos ;). Ihr könnt Eure Szene theoretisch unendlich klein oder aber unendlich groß darstellen. Das einzige was euch wirklich daran hindert ist die Größe und Auflösung der Euch zur Verfügung stehenden Typen wie Integer oder Single ;). Der eigentliche Größeneindruck eines Objektes entsteht durch die Geschwindigkeit mit der sich der Betrachter und andere Objekte in der Welt bewegen.&lt;br /&gt;
=== Der erste Kontakt ===&lt;br /&gt;
Um nun etwas mit OpenGL rendern zu können, müssen wir uns bewusst werden, was die Worldmatrix ist. In dieser Matrix wird festgehalten, wie und wo ein Objekt gezeichnet wird. Das hört sich vielleicht zunächst recht merkwürdig an, lässt sich aber leicht veranschaulichen.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns vor, die Worldmatrix zeigt auf einen Punkt, an dem ein Objekt gezeichnet werden soll (ganz übel wir werden später detaillierter darauf eingehen. Sollte es jemand also nach der folgenden Erläuterung nicht verstanden haben, kann er mich selbstverständlich persönlich per Mail zur &amp;quot;Rechenschaft&amp;quot; ziehen oder aber er wirft einen Blick in unser OpenGLWiki :)).&lt;br /&gt;
&lt;br /&gt;
Diesen Punkt setzen wir nun am Anfang in den Mittelpunkt unseres Koordinatensystems. Um oberes Beispiel aufzugreifen: Den Bildschirm. Dies geschieht mit dem Befehl [[glLoadIdentity]] und entspricht einem Reset der Worldmatrix. Theoretisch können wir nun an dieser Stelle etwas zeichnen. Dies würde allerdings dazu führen, dass das Objekt sehr groß oder gar nicht zu sehen ist, weil wir uns eben auch an diesen Stellen befinden. Gehen wir doch einmal 1,5 Einheiten nach links und 6 Einheiten nach hinten!&lt;br /&gt;
&lt;br /&gt;
Hierfür sollte man sich bewusst werden, dass wir in OpenGL praktisch an einem Stuhl gefesselt sind, d.h. wir können uns gar nicht bewegen. Das soll uns aber nicht davon abhalten. Wir brauchen ja nur die ganze Welt so zu bewegen, dass es für uns aussieht, als ob wir uns bewegen. Denn wenn sich alles außer uns nach links bewegt, haben wir den Eindruck, wir wären nach rechts gewandert, right?&lt;br /&gt;
&lt;br /&gt;
Nun aber zu der Bewegung unseres ersten Objektes:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5,0,0);&lt;br /&gt;
glTranslatef(0, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Dies hat bewirkt, dass sich unser Zeichenstift 1,5 Einheiten nach links (negativer Bereich der X-Achse) und anschließend 6Einheiten nach hinten bewegt hat. Ich habe diesen Fall absichtlich in zwei Schritten gefasst, um es zu verdeutlichen. Sicherlich wäre es einfacher, alles mit nur einem Aufruf von [[glTranslate|glTranslate*]] zu machen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Man beachte, dass in diesem Fall die 6 Schritte nach hinten notwendig sind um ein bisschen Distanz zum Objekt zu bekommen und nicht direkt in ihm zu stehen!&lt;br /&gt;
&lt;br /&gt;
Fertig! Schon haben wir dort unseren &amp;quot;Zeichenstift&amp;quot; positioniert, der nun auf weitere Zeichenkommandos von uns wartet. Das mag sicherlich alles ein wenig verwirrend klingen testet es am Besten aus und spielt mit den Parametern und erkennt, was gemeint ist :).&lt;br /&gt;
== Von Sichtungen... ==&lt;br /&gt;
=== Die Büchse der Pandora ===&lt;br /&gt;
Nun sind wir aber auch alle scharf darauf, endlich etwas zu rendern und auf dem Bildschirm auszugeben. Dies geschieht z.B. mit folgenden Zeilen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
  glVertex3f(-1,-1, 0);&lt;br /&gt;
  glVertex3f( 0, 1, 0);&lt;br /&gt;
  glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wir erkennen hierbei eindeutig eine Art Block. Gerade wir Pascaler sollten diese ja lieben :-&amp;gt;. Wir teilen OpenGL mit Hilfe von [[glBegin]] mit, dass wir ein Objekt zeichnen wollen. In diesem Fall übergeben wir den Parameter GL_TRIANGLE, der OpenGL angibt, dass folgende Punkte als ein Dreieck interpretiert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Anschließend folgt ein dreifacher Aufruf von [[glVertex|glVertex3f]]. Jeder Aufruf erzeugt nun einen Punkt (Vertex) in unserem 3D-Raum. Da wir OpenGL bei glBegin mitgeteilt haben, dass diese Punkte zu einem Dreieck zusammengefügt werden sollen wird das auch so getan ;).&lt;br /&gt;
&lt;br /&gt;
Wie wir auf dem Bild erkennen können, wurde unser Dreieck wie erwartet nach links verschoben abgebildet und auch mit einem leichten Abstand zur Kamera, nämlich 6 Einheiten entlang der Z-Achse.&lt;br /&gt;
=== Guter Stoff! ===&lt;br /&gt;
Nun ... ein wenig trostlos sieht unser Dreieck nun doch aus, oder? Ich habe übrigens damals bei D3D rund eine Woche benötigt, bis ich ein schwarzes Dreieck hatte. Wir haben immerhin schon ein weißes ... aber wir gehen nun einen Schritt weiter und werden das Dreieck schön bunt einfärben.&lt;br /&gt;
&lt;br /&gt;
Bevor nun irgendjemand anfängt und Pixel für Pixel den Bildschirm nach zu pinseln oder gar sein PaintShop bereits offen hat, um die ersten Texturen zu erstellen, sei gestoppt! Es gibt für einfache Einfärbungen in OpenGL eine bessere Methode. Wir definieren einfach für jeden Eckpunkt eine Farbe und OpenGL wird dann sogar eigenständig die Farbverläufe dafür erstellen. Jeder der D3D kennt, wird diese Vorgehensweise bekannt vorkommen und er wird beginnen verzweifelt nach dem FVF zu suchen, um es korrekt zu definieren... Wenn Ihr einen Vertex zeichnet, so rendert OpenGL diesen automatisch &amp;quot;weiß&amp;quot; (Ah huch! Deswegen ist unser Dreieck auch weiß???). Alles was wir nun machen müssen, ist OpenGL mitzuteilen, dass es eine andere Farbe einsetzen soll. Und zwar wird OpenGL diese Farbe für alle folgenden Eckpunkte nutzen, so lange bis von uns ein anderes Kommando kommt.&lt;br /&gt;
&lt;br /&gt;
Der mysteriöse Befehl, um den ich nun schon die ganze Zeit herumschwafle ist [[glColor|glColor*]]:&lt;br /&gt;
&amp;lt;pascal&amp;gt;// Alle folgenden Eckpunkte werden rot gefärbt&lt;br /&gt;
glColor3f(1,0,0);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wobei jeder Parameter einen Farbwert repräsentiert und zwar nach dem Muster RGB. Es wird ein Wert zwischen 1 und 0 erwartet, wobei eine Eins &amp;quot;volle Farbsättigung&amp;quot; bedeutet. Das heißt in unserem Fall haben wir als Farbe &amp;quot;rot&amp;quot; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Und weil wir schließlich die Welt ein wenig bunter machen und nicht nur das weiße Dreieck rot färben wollten, werden wir nach jedem Eckpunkt eine neue Farbe setzen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
  glColor3f(1, 0, 0); glVertex3f(-1,-1, 0);&lt;br /&gt;
  glColor3f(0, 1, 0); glVertex3f( 0, 1, 0);&lt;br /&gt;
  glColor3f(0, 0, 1); glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Und dies ist dann unser farbenfrohes Ergebnis. Beeindruckend, wenn man bedenkt, wie wenig Aufwand letztendlich dahinter steckt, oder?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_dreieck.gif]]&lt;br /&gt;
&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Wer meine Tutorials kennt weiß, dass zum Abschluß noch immer ein wenig Geblubber von mir kommt (man beachte diese entzückende Wortwahl von meiner einer hoffe, der Lektor findet es auch amüsant). (Anm. des Lektors: Und wie!) Schauen wir doch mal stolz auf das zurück, was wir heute erreicht haben! Wir haben OpenGL initialisiert, ein erstes Dreieck auf den Bildschirm gezaubert und dieses in den Farbtopf gesteckt! Das solltet Ihr als ein historisches Ereignis ansehen. Als ich damals mit D3D angefangen habe, brauchte ich, um es mir selbst zu erarbeiten, ca. eine Woche (Das ist jetzt der Moment, in dem Ihr Eure Hände heben solltest und ein lautes &amp;quot;Call me God&amp;quot; aus Euch herauskommen sollte, so dass zumindest Eure unmittelbaren Mitmenschen denken, dass Ihr einen Dachschaden habt!!! Das gehört einfach mit dazu ^__- )&lt;br /&gt;
&lt;br /&gt;
Wie immer solltet Ihr Euch nun hinsetzen und Euch ein wenig mit den Parametern vertraut machen. Speziell bei glTranslate* solltet Ihr ein wenig mit den Parametern experimentieren, damit Ihr seht, was es mit den Matrizen auf sich hat und wie diese funktionieren. Wenn Ihr dann auch denkt, dass Ihr damit vertraut seid, versucht ein wenig mit den einzelnen Vertexpositionen zu experimentieren und verändert diese. Wenn auch das klar ist, setzt Euch in die Ecke und warte sehnsüchtig auf mehr von uns :D! (Anm: die &amp;quot;Ecke&amp;quot; ist nicht die Kneipe nebenan ... :)&lt;br /&gt;
&lt;br /&gt;
Im nächsten Kapitel werden wir dann Matrizen-Hardcore machen ... legt also schon mal Euer Aspirin parat, es wird witzig werden *grunz* :).&lt;br /&gt;
&lt;br /&gt;
Und wie immer freuen wir uns sehr über Feedback. Schreibt uns doch einfach, sagt was Ihr gut und was hingegen Ihr als schlecht empfunden habt! Auch freuen wir uns immer über Ideen für weitere Tutorials, teilt uns also bitte Eure Ideen mit ;)!&lt;br /&gt;
&lt;br /&gt;
Okay ich wünsche Euch einen angenehmen Tag / Nacht!&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_3&amp;diff=7500</id>
		<title>Tutorial Lektion 3</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_3&amp;diff=7500"/>
				<updated>2005-05-02T16:36:27Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Eine Welt des Grauens =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Liebe Leser,&lt;br /&gt;
nachdem Ihr hoffentlich den kleinen Schock des letzten Tutorials alle gut überstanden habt, freue ich mich, Euch hier wieder begrüßen zu können. Wer dachte, dass die letzte Lektion bereits schwer war, der sollte dringend Urlaub nehmen. Seid gewarnt! Bevor ich jetzt richtig loslege, solltet Ihr einigermaßen entspannt sein. Wenn dies einer der Tage ist, an denen Ihr nur noch durch eine Kippe oder die Flasche Coke am Leben gehalten werdet, ordne ich erstmal eine kleine Zwangspause an ;).&lt;br /&gt;
&lt;br /&gt;
Der Stoff der jetzt kommt ist sicherlich nicht gerade die leichteste Lektüre. Wer Mathematik studiert, hat Vorteile, wer einigermaßen logisch denken kann auch. Ein Fachidiot, wie ich, hat nur eine Chance probieren, testen und lernen :). Und weil ich weiß, wie schwer es eventuell sein kann, werde ich nun einfach mal versuchen, ganz simpel anzufangen und das Ganze mit vielen Bildern so gut wie nur irgend möglich zu illustrieren. &lt;br /&gt;
&lt;br /&gt;
Und wenn Ihr nun Angst habt, dass Ihr das nicht packt, weil ich hier so eine Panik verbreite, dann solltet Ihr mich sehen, wie ich hier verzweifelt vor meinen Tasten hänge und mich frage, wie ich das alles bloß in Worte fassen soll :). Aber was soll es? Ran an den Kram!!! Heulen könnt Ihr anschließend im Forum ;).&lt;br /&gt;
== Das Grauen hat einen Namen ==&lt;br /&gt;
=== &amp;quot;Kinofilm&amp;quot; vs. &amp;quot;Bahnhof&amp;quot; ===&lt;br /&gt;
Wer kennt nicht &amp;quot;Matrix&amp;quot; und hätte gedacht, dass es davon nicht nur eine, sondern unendlich viele gibt die so genannten &amp;quot;Matrizen&amp;quot;. Vor allem am Anfang werden diese Dinger Euch das Leben erschweren und Ihr werdet leichte Neigungen tief in Euch verspüren, dass am besten Euer ganzes Projekt sich nur im Zentrum Eurer Welt abspielt (und dies ist nicht im wahrsten Sinne des Wortes gemeint).&lt;br /&gt;
&lt;br /&gt;
Wer mit Matrizen umgehen kann, beherrscht das Wichtigste an der 3D-Programmierung. Wer nicht zu den Genies zählt, sollte nicht sofort aufgeben, sondern sich viele Beispiele ansehen und viel mit diesen herumspielen.&lt;br /&gt;
&lt;br /&gt;
Wie auch immer Ihr solltest wissen, dass es bei jedem Rendervorgang mehrere Matrizen gibt, die ganz drastisch das Aussehen der Szene bestimmen. Es gibt in OpenGL drei Bereiche, in denen Matrizen eingesetzt werden. Die so genannte World- oder Modelviewmatrix, die Texturenmatrix und die Perspektivenmatrix. Die zweifellos wichtigste dieser Matrizen ist die Worldmatrix, da sie die Position Eures Zeichenstiftes beschreibt und somit Objekte positioniert. Die Texturenmatrix funktioniert fast genauso wie die Worldmatrix nur definiert sie die Ausrichtung der Texturen. Wir werden später auf sie zurückkommen. Die Perspektivenmatrix definiert wesentliche Eigenschaften des Blickfeldes des Betrachters.&lt;br /&gt;
&lt;br /&gt;
Der Befehl [[glMatrixMode]] erlaubt eine Änderung der aktuellen Matrix. Mit Hilfe der Konstanten GL_MODELVIEW, GL_TEXTURE oder GL_PERSPECTIVE kann man die Matrix bestimmen. Die Namen der Konstanten sind soweit hoffentlich selbst erklärend. Von nun an bewirken alle Matrixoperationen wie beispielsweise [[glLoadIdentity]] oder [[glTranslate|glTranslate*]] eine Veränderung der aktuell gesetzten Matrix.&lt;br /&gt;
=== Die Perspektivenmatrix ===&lt;br /&gt;
Wie bereits erwähnt beschreibt die Perspektivenmatrix das aktuelle Sichtfeld. Zum Setzen der Perspektivenmatrix verwendet man in der Regel Befehle wie [[glFrustum]], [[gluPerspective]], [[glOrtho]] oder [[glOrtho2D]].&lt;br /&gt;
&lt;br /&gt;
gluPerspective lässt den Raum beispielsweise dreidimensional erscheinen, indem sich die Größe von Objekten mit zunehmender Entfernung vom Betrachter verringert. Diese Verringerung ist abhängig von dem im ersten Parameter übergebenen Winkel. &lt;br /&gt;
&lt;br /&gt;
glOrtho hingegen ist phantastisch für ein 2D-Blickfeld geeignet, denn diese Art der Projektion enthält keine Tiefe mehr.&lt;br /&gt;
&lt;br /&gt;
Genauere Informationen zu den einzelnen Funktionen könnt ihr unserem OpenGL-Wiki entnehmen.&lt;br /&gt;
&lt;br /&gt;
Auf eine Sache möchte ich jedoch noch eingehen: Einige dieser Funktionen verlangen die Parameter znear und zfar. Diese Parameter beschreiben die zwei Schnittflächen, die das Blickfeld vor dem Betrachter begrenzen. &amp;quot;znear definiert die Entfernung der Nearclippingplane vom Betrachter. Alle Objekte, die sich vor dieser Ebene befinden sind nicht sichtbar. zfar beschreibt die Entfernung der Farclippingplane vom Betrachter. Alle Objekte, die sich hinter dieser befinden werden weggeschnitten. Wenn also wieder einmal nur die Hälfte Eurer Szene auf dem Bildschirm sichtbar ist, versucht die Schnittflächen entsprechend anzupassen!&lt;br /&gt;
== Die Worldmatrix ==&lt;br /&gt;
=== D3D-Verrat ===&lt;br /&gt;
Wenn Ihr ebenfalls zu den D3D-Verrätern gehört (wie z.B. ich *g*), dann solltet Ihr Euch möglichst von eurer Denkweise trennen: Jede Positionierung der Kamera erfolgt über ein Drehen und Bewegen der Szene. Das ist vor allem am Anfang ein wenig gewöhnungsbedürftig (&amp;quot;Die Welt dreht sich! Nicht Du!&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Vielmehr wird jede Manipulation direkt an die Worldmatrix übergeben. Das heißt, wenn Ihr glTranslate* aufruft, so ist diese Manipulation bereits bei Euch in die Worldmatrix eingetragen, alle weiteren Objekte werden mit dieser Matrix transformiert. Wer zweimal glTranslate*(2, 0, 0) aufruft wird feststellen, dass glTranslate* nicht zwei Matrizen zurückliefert, sondern nur eine, die dann auf (4, 0, 0) verweist. Am Anfang solltet Ihr also sehr darauf achten, es wird eine Weile dauern bis Ihr dies fest in Eurem Herzen tragt. Nicht sofort aufgeben :)!&lt;br /&gt;
== Einfach, Kompakt und Funktional ==&lt;br /&gt;
Neben dem Befehl glTranslate*, den wir im letzten Tutorial lieben gelernt haben, gibt es noch weitere Befehle, die sich auf die einzelnen Matrizen auswirken und auf die ich in dem folgenden Abschnitt eingehen möchte.&lt;br /&gt;
=== Dreh- und Angelpunkt des Geschehens ===&lt;br /&gt;
Zunächst beschäftigen wir uns mit der Rotation. Wir versuchen ein Objekt zu erzeugen, welches um 90° um seine eigene Achse gedreht wurde. Das ist nicht sonderlich schwer: &amp;lt;pascal&amp;gt;[[glRotate|glRotatef]](90,0,1,0);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Ein Objekt auf das wir diese Matrix anwenden, wird um 90° um seine Y-Achse gedreht sein. Daraus schließen wir, dass der erste Parameter den Winkel im Gradmaß um den wir rotieren möchten definiert und die 3 folgenden Parameter den Vektor beschreiben um den die Rotation durchgeführt werden soll. Rotationen bergen tatsächlich eine Schwierigkeit, denn es ist nicht immer einfach ein Objekt um die Eigene Achse zu rotieren. Verschiebt Ihr euer Objekt zuerst und beginnt dann die Rotation, so rotiert das Objekt um die eigene Achse.&lt;br /&gt;
&lt;br /&gt;
Ruft Ihr jedoch zuerst glRotate* und anschließend glTranslate* auf, so unterscheidet sich erzielte Ergebnis von dem vorherigen.&lt;br /&gt;
&lt;br /&gt;
Um diesen Problemen aus dem Weg zu gehen so müsst Ihr Euch vorstellen, dass Ihr den Rotationspunkt im Moment des Aufrufs von glRotate* setzt. Verschiebt Ihr Euer Objekt anschließend so bleibt der Rotationspunkt derselbe und das Objekt beginnt den Rotationspunkt auf einer Bahn zu umkreisen. So gesehen gibt es keinen wirklichen Unterschied und die Rotation um die eigene Achse ist ein Ausnahmefall, denn der Rotationspunkt liegt dann in dem von uns erwarteten Mittelpunkt des Objektes.&lt;br /&gt;
=== Eine Frage der Größe ===&lt;br /&gt;
Nun ja was kann man denn noch alles in einer 3D-Welt machen? Ihr habt gelernt, wie man Objekte bewegt und diese durch Rotationen ausrichten kann. Das ist doch schon eine Menge zum Spielen oder? Nun, bei einer Transformation kann für uns noch eine Sache sehr wichtig werden, nämlich die Möglichkeit, zu bestimmen in welcher Größe ein Objekt dargestellt werden kann.&lt;br /&gt;
&lt;br /&gt;
Sicher würde es Sinn machen ein benötigtes Objekt gleich in der richtigen Größe in die Anwendung zu laden. Manchmal ist es aber von Vorteil, wenn man die Größe eines Objektes ohne großen Aufwand verändern kann oder aber mehrere Objekte desselben Typs mit unterschiedlicher Größe darzustellen.&lt;br /&gt;
&lt;br /&gt;
Eine Größenveränderung ist mit Hilfe des Befehls [[glScale|glScale*]] möglich.&lt;br /&gt;
&amp;lt;pascal&amp;gt;glScalef(1,1,1);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
In diesem Fall würden wir das Objekt so zeichnen, wie wir es auch angegeben haben. Das heißt in seiner Originalgröße. Sicherlich ahnst Du bereits, was die Parameter aussagen sie stehen für das Verhältnis der einzelnen Seiten nach dem Muster X, Y und Z. Würden wir als ersten Parameter statt einer 1 eine 2 einsetzen, würde unser Objekt in seiner räumlichen Ausdehnung bezogen auf der X-Achse doppelt so groß sein. Würden wir stattdessen 0.5 angeben, wäre es nur noch halb so groß.&lt;br /&gt;
&lt;br /&gt;
In Wirklichkeit bewirkt glScale* jedoch keine Veränderung der Größe sondern eine Verzerrung unseres Koordinatensystems. Daher wirkt jeder Aufruf von glScale* auch auf Befehle wie glTranslate*. Aus Sicht der Matrizen lässt sich dieses Phänomen auch recht leicht erklären. In Wirklichkeit erzeugt jeder Aufruf von glRotate*, glTranslate* oder glScale* eine eigene Matrix, die dann mit der aktuellen Matrix (z.B. der Modelviewmatrix) multipliziert wird. Wurde in der Modelviewmatrix bereits ein glScale* verewigt, so wirkt sich dieses bei der Multiplikation der Matrizen auf die Transformationsmatrix aus.&lt;br /&gt;
&lt;br /&gt;
Ich denke ich muss nicht näher darauf eingehen, dass es keine gute Idee ist das Koordinatensystem mit einem Aufruf von glScalef(0, 0, 0) zu zerstören. Was würde es auch für einen Sinn ergeben, das Koordinatensystem in einem Punkt unterzubringen? &lt;br /&gt;
&lt;br /&gt;
Ich hoffe ich habe Euch nun nicht den letzten Funken Hoffnung OpenGL zu verstehen geraubt. Ich kann Euch versichern, dass dieses Verständnis mit der Zeit heranreifen wird.&lt;br /&gt;
[[bild:tutimg_lektion3_skalierung.gif|256px|right]]&lt;br /&gt;
glScale* ist aber aufgrund seiner phantastischen Eigenschaften nicht nur in der Lage die Größe von Objekten zu verändern sondern es ist auch möglich Objekte zu spiegeln indem man negative Werte an glScale* übergibt. Somit kann sich z.B. ein D3D-Umsteiger das leben vereinfachen indem er mit einem Aufruf von glScalef(1, 1, -1) sicherstellt, dass die Z-Achse in den Bildschirm hinein positiv verläuft.&lt;br /&gt;
&lt;br /&gt;
Jeder, der die Funktion der Modelviewmatrix begreifen möchte, dem möchte ich das Programm Matrixcontrol von Lithander (siehe Anhang) ans Herz legen. Es erlaubt Euch bestimmte Änderungen an der Matrix direkt nachzuvollziehen und wenn man mit dem Programm ein wenig umherspielt wird selbst dem letzten ziemlich schnell ein Licht aufgehen. Wenn nicht, dann hilft nur fleißiges Programmieren und Anwenden und irgendwann klatscht es dann laut, wenn die eigene Handfläche auf der Stirn zum stehen kommt ;).&lt;br /&gt;
== Virtuelle Gedächtnisse ==&lt;br /&gt;
=== Vom Pushen und Poppen ===&lt;br /&gt;
Wer diesen Titel ließt und sich nun zwangsläufig daran erinnert, was er bereits alles in seinem Leben konsumiert hat oder neben wenn er am nächsten Morgen aufgewacht ist, sei entwarnt! Wir reden hier von etwas ganz anderem&lt;br /&gt;
&lt;br /&gt;
Wie wir bereits gelernt haben, verändert jeder Aufruf von glTranslate*, glRotate* oder glScale* die Worldmatrix und wirkt sich unmittelbar auf andere Objekte aus. Dies kann durchaus sehr erwünscht sein. Wenn wir allerdings in einer großen Welt verschiedene Objekte positionieren, kann dies schnell zum Fluch werden. Natürlich können wir dem entgegenwirken und zum Beispiel jedes Mal glLoadIdentity aufrufen. Dies hat jedoch den Nachteil, dass die World- Matrix dann eben wieder leer ist und wir z.B. die Camera erst wieder setzen müssen, damit die Objekte an die richtige Stelle transformiert werden.&lt;br /&gt;
&lt;br /&gt;
Eine weitaus elegantere Lösung ist die Verwendung des &amp;quot;Matrixstacks&amp;quot;! Jeder Aufruf von [[glPushMatrix]] bewirkt, dass die momentane Matrix auf den Stack geschrieben wird. Alle Manipulationen, die wir dann durchführen, werden wie gewohnt vollzogen. Ist alles gezeichnet, rufen wir mit [[glPopMatrix]], die letzte Matrix vom Stack wieder herunter und haben im Prinzip den letzten Zustand vor unseren Veränderungen rekonstruiert und können dann wieder anfangen, auf dieser Matrix aufzubauen. Natürlich lassen sich auch mehre Matrizen auf den Stack pushen! Dies kann reichlich Zeit sparen, wenn man bedenkt, dass man ansonsten andauernd die Matrix der Szene neu setzen muss.&lt;br /&gt;
&lt;br /&gt;
Um das ganze etwas anschaulicher zu machen, verwenden wir ein einfaches Beispiel. Wir werden zwei Dreiecke jeweils rechts und links vom Ursprung zeichnen. Nachdem wir das linke Objekt gezeichnet haben, werden wir nicht glLoadIdentity einsetzen oder das zweite Objekt entsprechend nach rechts transformieren, sondern eben den Matrixstack zu Hilfe nehmen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;glLoadIdentity;&lt;br /&gt;
glTranslatef(0,0,-10);&lt;br /&gt;
glPushMatrix;&lt;br /&gt;
  glTranslatef(-2,0,0);&lt;br /&gt;
  glBegin(GL_TRIANGLES);&lt;br /&gt;
    glColor3f(1,0,0); glVertex3f(-1,-1, 0);&lt;br /&gt;
    glColor3f(0,1,0); glVertex3f( 0, 1, 0);&lt;br /&gt;
    glColor3f(0,0,1); glVertex3f( 1,-1, 0);&lt;br /&gt;
  glEnd;&lt;br /&gt;
glPopMatrix;&lt;br /&gt;
&lt;br /&gt;
glTranslatef(2,0,0);&lt;br /&gt;
glBegin(GL_TRIANGLES);&lt;br /&gt;
  glColor3f(1,0,0); glVertex3f(-1,-1, 0);&lt;br /&gt;
  glColor3f(0,1,0); glVertex3f( 0, 1, 0);&lt;br /&gt;
  glColor3f(0,0,1); glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wie Ihr seht, setzen wir am Anfang praktisch die Distanz zum Objekt, speichern die Matrix und zeichnen das erste Objekt. Wir setzen dann die Matrix wieder zurück, so dass sie nur noch den Aufruf von glTranslatef(0, 0, -10) beschreibt und transformieren das zweite Objekt fertig. Man kann auch ohne diese Matrixstacks leben sie können einem aber das Leben auch sehr erleichtern.&lt;br /&gt;
== I wanna all! ==&lt;br /&gt;
Wer glaubt, dass es das bereits war der irrt. Es gibt noch weitere Möglichkeiten auf die Matrix Einfluss zu nehmen. Der Befehl [[glLoadMatrix|glLoadMatrix*]] erlaubt es eine beliebige 4x4 Matrix zu laden und die aktuelle Matrix durch die geladene komplett zu ersetzen.&lt;br /&gt;
&lt;br /&gt;
Der Befehl [[glMultMatrix|glMultMatrix*]] multipliziert die übergebene 4x4-Matrix mit der aktuellen Matrix. Mit diesem Befehl könnte man beispielsweise eigene glScale*- und glRotate*-Befehle schreiben, obgleich sich auch hier über den Sinn streiten lässt. Eine sinnvollere Anwendungsmöglichkeit wird in einem späteren Tutorial vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Der Befehl [[glGet|glGet*]] mit den Tokens GL_MODELVIEW_MATRIX, GL_TEXTURE_MATRIX und GL_PROJECTION_MATRIX ermöglicht euch die einzelnen Matrizen anzufordern.&lt;br /&gt;
== Weltenformeln ==&lt;br /&gt;
=== Hier kommt die Sonne ===&lt;br /&gt;
Genug der Theorie! Es wird langsam Zeit für etwas Praxis&lt;br /&gt;
&lt;br /&gt;
Nun, um ehrlich zu sein, habe ich an der folgenden Idee ein wenig Zeit benötigt, um ein einigermaßen gut anschauliches Beispiel zu finden ich will hier nicht weiter darauf eingehen, was ich gerade gehört habe, als mir die Sonne aufging :-D.&lt;br /&gt;
&lt;br /&gt;
Wie auch immer, man kann komplexere Matrixtransformationen sehr leicht mit unseren Sonnensystem beschreiben (Hey, wenn jetzt jemand denkt, dass ich spinne). Um das Ganze etwas übersichtlicher zu gestalten, werden wir unser Prinzip auf Sonne, Mond und Erde beschränken.&lt;br /&gt;
&lt;br /&gt;
Wie funktioniert unser Sonnensystem? (Warnung, der Autor betritt mal wieder seine ausgeprägte Fantasywelt! [Anm. d. Lektors: Die richtige Sprache dafür hat er ja schon]).&lt;br /&gt;
&lt;br /&gt;
Die Sonne steht im Mittelpunkt und sollte sich in unserem Beispiel nicht selbst bewegen. Sie ist einfach nur im Mittelpunkt und vegetiert dort vor sich hin! Nun gibt es einen kleinen blauen Planeten, namens Erde (wieso er im Sample ein Dreieck ist, sei Eurer Kreativität überlassen), der zum einen um seine eigene Achse rotiert, viel wichtiger jedoch, sich auch noch um die Sonne dreht. Nun werden sich vor allem die Neulinge unter Euch sadistisch freuen, das Fenster schließen, ihr Delphi starten und drauf los proggen! Das ist doch alles kein Ding, der gerade mal frisch aufgeschnappte Sinus-Satz lässt sich prima mit einbringen! Und schon berechnet man mit Hilfe von Sinus, die Position auf der Kreisbahn und positioniert den Planeten mit glTranslate* an seine Position. Und oh Wunder es klappt. HALT! Wer es nicht gemerkt hat, da war ne Portion Ironie dabei. Bitte Weiterlesen ^__ ^!&lt;br /&gt;
&lt;br /&gt;
Denn spätestens wenn wir folgende Ergänzung zum Besten geben, werden die ersten Augen wässrig werden, weil die meisten Hirne einem Informationskoller unterliegen. Meines stieg ja schon beim einfachen Sinus aus :-D. Ab und an kann man nämlich nachts weißgräuliche Flecken am Himmel beobachten! Wer annimmt, dass es sich hierbei um eine geschickt platzierte, in Echtzeit berechnete, Textur handelt, ist schief gewickelt! Es handelt sich dabei nämlich um ein Decal, namens Mond. Oha so schlimm war es schon lange nicht mehr. Dieser bewegt sich in unserem Beispiel auch nicht entlang der Erdachse, sondern auf einer schiefen Bahn, damit man auf der unteren Hemissphäre den Mond auch am Tage noch sehen kann ^___^ (*selbstgefälliges, göttliches Grinsen*). Dies lässt sich nur sehr schwer mit Sinus beschreiben. Bevor wir uns nun jedoch mit einem Block bewaffnen oder den nächsten Mathematik-Professor entführen, damit er die Mathematik für uns übernimmt, greifen wir lieber zu den Sternen und nehmen ein einfacheres Verfahren! Les Matrices!&lt;br /&gt;
=== Und es dreht sich doch! ===&lt;br /&gt;
Die Vorgehensweise ist eigentlich relativ simpel. Wir Zeichnen unsere Sonne im Mittelpunkt unseres Universums. Mit dem Aufruf von glRotate* setzen wir den Rotationspunkt an die Position unseres Zeichenstiftes. In unserem Fall ist das noch immer die Position der Sonne. &lt;br /&gt;
&lt;br /&gt;
Nun verschieben wir die Erde nach links und die erste Hürde ist genommen. Jetzt müssen wir nur noch den Mond setzen und das funktioniert genauso einfach wie zuvor mit der Erde.&lt;br /&gt;
&lt;br /&gt;
Unser Zeichenstift befindet sich nun an der Position der Erde und daher rufen wir glRotate* auf. Nun müssen wir den Zeichenstift nur noch ein kleines Stück neben der Erde positionieren und den Mond zeichnen. Voila! Es ist vollbracht!&lt;br /&gt;
&lt;br /&gt;
Wenn man genauer darüber nachdenkt erkennt man sehr schnell wie elegant man dieses verhältnismäßig komplizierte Problem gelöst hat.&lt;br /&gt;
&lt;br /&gt;
Wer nun auf Wolke Sieben schwebt und glaubt er könnte sich nun an den nächsten DOOMTitel werfen, der sollte das Programm zuvor noch so erweitern, dass die Sonne, die Erde und auch der Mond sich zusätzlich um die eigene Achse drehen.&lt;br /&gt;
== Timebased Movement ==&lt;br /&gt;
Wer bereits versucht hat eines der ersten selbst geschriebenen OpenGL-Programme voller Stolz seinem Kumpel vorzuführen wird festgestellt haben, dass die Bewegungen auf dem anderen Rechner schneller oder langsamer abgelaufen sind als es auf dem eigenen Rechner der Fall war.&lt;br /&gt;
&lt;br /&gt;
Dieses Phänomen lässt sich sehr einfach erklären. Nehmen wir an wir bewegen ein Dreieck von links nach rechts um den Wert 1 über den Bildschirm. Eine alte Krücke wie mein PC schafft vielleicht 50 FPS. Das bedeutet das Objekt wird in einer Sekunde genau 50mal um eine Einheit nach rechts verschoben. Das bedeutet insgesamt also um 50 Einheiten in einer Sekunde. Wenn das Programm nun aber auf einem High-End-System läuft werden wir die Szene sagen wir 500mal aktualisieren können. Folglich bewegt sich auf diesem Rechner das Dreieck in einer Sekunde um 500 Einheiten.&lt;br /&gt;
&lt;br /&gt;
Das einzige was wir von unserem Dreieck erhaschen können ist ein blitzartiges Zucken auf dem Bildschirm, welches wir schnell als optische Täuschung abtun würden. Wie kann man diesem Problem nun aber entgegen wirken?&lt;br /&gt;
&lt;br /&gt;
Nehmen wir an wir kennen die Zeit, die wir zum Zeichnen eines Frames benötigen und ermitteln anhand dieses Wertes einen Zeitfaktor, den wir in die Bewegung mit einfließen lassen.&lt;br /&gt;
&amp;lt;pascal&amp;gt;NewPosition := OldPosition + Movement * TimeFactor;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Handelt es sich um einen schnellen Rechner so ist der Zeitfaktor entsprechend niedrig und die Bewegung pro Frame verringert sich. Ist der Rechner hingegen langsam so besitzen wir einen hohen Zeitfaktor. Folglich legt das Dreieck auf dem schnelleren Rechner pro Frame weniger Weg zurück als auf dem langsamen. Insgesamt jedoch legen die beiden Dreiecke im gleichen Zeitabstand (z.B. in einer Sekunde) denselben Weg zurück.&lt;br /&gt;
&lt;br /&gt;
Um den Zeitfaktor zu ermitteln muss man lediglich die Zeit für einen Schleifendurchlauf ermitteln. Um eine möglichst hohe Genauigkeit zu erhalten sollte man die Zeit für den letzten Schleifendurchlauf ermitteln und im aktuellen Schleifendurchlauf verwenden.&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Wow und wieder ein wenig Zeit zum Ausspannen und ein paar persönlichen Worten. Ich kann getrost nur eines sagen: Wenn Ihr nun denkt &amp;quot;das war alles ja sehr leicht&amp;quot; habt Ihr irgendetwas falsch gemacht und solltet das Tutorial noch einmal von Vorn durcharbeiten ;). Wenn Ihr jedoch leichte Kopfschmerzen verspürt (ob es nun die Matrizen sind oder der fiese Elementarbereich *sg*) so habt Ihr alles richtig gemacht ;).&lt;br /&gt;
&lt;br /&gt;
Matrizen sind vor allem vielen Einsteigern sehr fremd. &amp;quot;Übung macht den Meister&amp;quot;. Versucht Euch doch einfach mal die eine oder andere Aufgabe selbst zu stellen oder unser &amp;quot;Sonnensystem&amp;quot; selbst einmal nachzuschreiben. Wenn Ihr glaubt, dass das Ganze ganz nett geworden ist, dann schickt es mir doch einfach mal zu. Ich freue mich immer darüber zu sehen, was für Früchte meine Tutorials tragen. *lach* Und wenn sich plötzlich alles um die Erde dreht, dann habe ich a) das Gefühl, dass die Kenntnisse über das Sonnensystem nicht mehr ganz up to date sind oder b) ich einen ziemlich fatalen Fehler beim Erklären gemacht habe :-&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Schreckt auch bitte nicht davor zurück, eine Frage diesbezüglich im Forum zu stellen. Es ist keine Schande, mit einer Matrix Probleme zu haben und vor allem die Erfahrenen unter uns, sollten nur zu gut wissen, was alles die Ursache dafür sein kann, wenn man plötzlich gar nichts mehr auf dem Screen sieht :).&lt;br /&gt;
&lt;br /&gt;
Wir selbst werden uns in den folgenden Kapiteln noch etwas intensiver mit den Matrizen beschäftigen und unter anderem die eine oder andere interessante Spielerei zeigen!&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Anhang ==&lt;br /&gt;
&lt;br /&gt;
[http://www.pixelpracht.net Pixelpracht] -  Hier könnt Ihr das Programm Matrix Control finden&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=7490</id>
		<title>Tutorial Lektion 2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=7490"/>
				<updated>2005-05-02T16:33:06Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: Ausrichtung der Bilder&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Entdeckung einer neuen Welt =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Ich möchte Euch an dieser Stelle bei DGL herzlich willkommen heißen. Vermutlich wird dies eines der ersten Tutorials sein, das Ihr als Einsteiger lesen werdet. Wahrscheinlich werdet Ihr dann auch noch nicht lange bei uns sein und Euch nicht vorstellen können, dass all die Schreiber auf unserer Seite keine Gurus, sondern ganz normale Menschen sind.&lt;br /&gt;
&lt;br /&gt;
Man kann uns also jeder Zeit im Forum anfassen, uns Fragen stellen, Vorschläge unterbreiten oder einfach nur einmal kurz mit einem Lob ermutigen weitere Texte zu verfassen ;-).&lt;br /&gt;
&lt;br /&gt;
Ich wünsche Euch an dieser Stelle viel Erfolg bei dem Einstieg in die Thematik OpenGL und ermahne Euch noch einmal, dass Ihr Eure Ziele nicht zu weit steckt. Wirklich Spaß beginnt OpenGL nämlich erst dann zu machen, wenn man stets kleinere Erfolge feiern kann.&lt;br /&gt;
== Höhere Mächte - Matrizen und ihre Folgen ==&lt;br /&gt;
=== Saubere Arbeit ===&lt;br /&gt;
Bevor wir direkt beginnen etwas zu Zeichnen müssen wir erst einmal das Bild löschen, denn wie in der vorherigen Lektion beschrieben zeichnen wir die Szene jeden Schleifendurchlauf neu. Das Löschen der Puffer, in dem die Bildinformationen enthalten sind übernimmt die Funktion [[glClear]]. Die Farbinformationen unser  [[Fragment|Fragmente]] (Fragmente sind vergleichbar mit den [[Pixel|Pixeln]] auf dem Bildschirm besitzen aber weitere Informationen wie z.B. Tiefenwerte. Bei der Ausgabe des Bildes werden diese Fragmente in Pixel umgewandelt) sind in dem so genannten [[Farbpuffer]] (Colorbuffer) gespeichert. Aus diesem Grund übergeben wir an die Funktion glClear die Konstante GL_COLOR_BUFFER_BIT.&lt;br /&gt;
&amp;lt;pascal&amp;gt;//Farbbuffer entleeren&lt;br /&gt;
glClear(GL_COLOR_BUFFER_BIT);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
[[bild:tutimg_lektion2_puffereffekt.gif|right]]&lt;br /&gt;
Mit Hilfe des Befehls [[glClearColor]] können wir festlegen, welche Farbinformationen mit dem Aufruf von glClear in den Colorbuffer geschrieben werden sollen. Wenn wir es also genau nehmen so löscht glClear den Colorbuffer nicht, sondern es schreibt ihn mit den definierten Werten voll. Standardmäßig erhalten die Fragmente eine schwarze Farbe.&lt;br /&gt;
&lt;br /&gt;
Es wird also nicht bei jedem Zeichenvorgang (Rendervorgang) der Bildspeicher gelöscht, sondern der Programmierer entscheidet, wann dies geschehen soll. Theoretisch könnt Ihr auch die Szene wiedergeben und dann löschen, bevor sie ausgegeben wird... wer's mag :).&lt;br /&gt;
&lt;br /&gt;
Wer sich entscheidet den Colorbuffer nicht zu löschen, der kann so auch einige nette Effekte erzeugen. Den Cheatern unter euch sollte der erreichte Effekt bekannt vorkommen, wenn man beispielsweise bei Counter-Strike durch die Wand gelaufen ist. Der Grund für das Verwischen ist in beiden Fällen derselbe: Das neue Bild wird gezeichnet, ohne dass das alte Bild aus dem Puffer entfernt wurde.&lt;br /&gt;
=== Und die Welt ist doch keine Scheibe ===&lt;br /&gt;
[[bild:tutimg_lektion2_koordinatensystem.gif|right]]&lt;br /&gt;
Nachdem wir nun wieder Ordnung im Speicher geschafft haben, können wir zum interessanten Teil kommen: &amp;quot;Wie darf man sich einen 3D-Raum vorstellen?&amp;quot; Nun  warum schaut Ihr Euch nicht einmal in Eurem Zimmer um?&lt;br /&gt;
&lt;br /&gt;
Versuchen wir doch mal, ein Beispiel direkt aus dem Leben gegriffen zu nehmen und stellen uns unsere Umgebung als Koordinaten-System vor (Igitt!). Der Monitor, der hoffentlich direkt vor uns steht, ist in diesem Fall unser Ursprung, d.h. er liegt an dem Punkt (0, 0, 0).&lt;br /&gt;
&lt;br /&gt;
Blicken wir seitwärts neben den Monitor, so sehen wir eine Linie (wenn Ihr es nicht tun solltest, macht Euch keine Sorgen  solche Anfälle hat der Autor häufiger *g*), die von links nach rechts verläuft. Es handelt sich hierbei um die X-Achse, die links vom Monitor im negativen Bereich verläuft, rechts davon in den positiven.&lt;br /&gt;
&lt;br /&gt;
Nun blicken wir einmal nach oben und einmal nach unten und schon erspähen wir die Y-Achse, die oberhalb des Monitors positiv verläuft, unterhalb negativ. Wunderbar! Wenn Ihr bereits in 2D gearbeitet habt, solltet Ihr an dieser Stelle ein dümmliches Grinsen auf Eurem Gesichte haben und das wohltuenden Gefühl, dass Euch das doch alles bereits irgendwie bekannt vorkommt. Doch zu unserem Entsetzen können wir uns ja auch noch von unserem Bildschirm wegbewegen oder auch dichter heran (alle Kurzsichtigen unter uns sollten das nicht so persönlich nehmen, auch Sie leben in einem 3D-Raum ^__-).&lt;br /&gt;
&lt;br /&gt;
Dieses Phänomen ist im 3D-Raum typisch, jedoch nicht unerklärlich, da wir uns auf der Z-Achse bewegen. Rollen wir mit dem Stuhl vom Monitor weg, so gelangen wir in den positiven Bereich der Z-Achse, bewegen wir uns drauf zu, gelangen wir in den negativen Bereich. Jeder, der bereits in D3D programmiert hat, sollte sich schleunigst einprägen, dass das ein großer Unterschied zwischen D3D und OpenGL ist. Das kann sonst zu einigen wirklich fiesen Fehlern führen, wenn man es nicht weiß *fg*.&lt;br /&gt;
&lt;br /&gt;
Soweit so gut! Klingt bisher hoffentlich immer noch nicht so kompliziert. Nur keine Sorge, das Niveau versuchen wir zu halten ;).&lt;br /&gt;
&lt;br /&gt;
Speziell wenn Ihr bereits 2D-Spiele programmiert habt, solltet Ihr Euch sehr schnell von folgenden Gedanken trennen: Die Koordinaten, die Ihr seht und angebt, entsprechen in der Regel nicht den Pixeln des Bildschirmes, sondern so genannten Weltkoordinaten. Eine Definition für diese Weltkoordinaten gibt es nicht, denn wie groß diese sind ist dem Programmierer überlassen. Ob Ihr euer Objekt eine Einheit vor Euch und 0,1 Einheit rechts von Euch oder aber 100 Einheiten vor euch und 10 Einheiten neben Euch positioniert ist egal. Die euch zur Verfügung stehende Welt ist grenzenlos ;). Ihr könnt Eure Szene theoretisch unendlich klein oder aber unendlich groß darstellen. Das einzige was euch wirklich daran hindert ist die Größe und Auflösung der Euch zur Verfügung stehenden Typen wie Integer oder Single ;). Der eigentliche Größeneindruck eines Objektes entsteht durch die Geschwindigkeit mit der sich der Betrachter und andere Objekte in der Welt bewegen.&lt;br /&gt;
=== Der erste Kontakt ===&lt;br /&gt;
Um nun etwas mit OpenGL rendern zu können, müssen wir uns bewusst werden, was die Worldmatrix ist. In dieser Matrix wird festgehalten, wie und wo ein Objekt gezeichnet wird. Das hört sich vielleicht zunächst recht merkwürdig an, lässt sich aber leicht veranschaulichen.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns vor, die Worldmatrix zeigt auf einen Punkt, an dem ein Objekt gezeichnet werden soll (ganz übel wir werden später detaillierter darauf eingehen. Sollte es jemand also nach der folgenden Erläuterung nicht verstanden haben, kann er mich selbstverständlich persönlich per Mail zur &amp;quot;Rechenschaft&amp;quot; ziehen oder aber er wirft einen Blick in unser OpenGLWiki :)).&lt;br /&gt;
&lt;br /&gt;
Diesen Punkt setzen wir nun am Anfang in den Mittelpunkt unseres Koordinatensystems. Um oberes Beispiel aufzugreifen: Den Bildschirm. Dies geschieht mit dem Befehl [[glLoadIdentity]] und entspricht einem Reset der Worldmatrix. Theoretisch können wir nun an dieser Stelle etwas zeichnen. Dies würde allerdings dazu führen, dass das Objekt sehr groß oder gar nicht zu sehen ist, weil wir uns eben auch an diesen Stellen befinden. Gehen wir doch einmal 1,5 Einheiten nach links und 6 Einheiten nach hinten!&lt;br /&gt;
&lt;br /&gt;
Hierfür sollte man sich bewusst werden, dass wir in OpenGL praktisch an einem Stuhl gefesselt sind, d.h. wir können uns gar nicht bewegen. Das soll uns aber nicht davon abhalten. Wir brauchen ja nur die ganze Welt so zu bewegen, dass es für uns aussieht, als ob wir uns bewegen. Denn wenn sich alles außer uns nach links bewegt, haben wir den Eindruck, wir wären nach rechts gewandert, right?&lt;br /&gt;
&lt;br /&gt;
Nun aber zu der Bewegung unseres ersten Objektes:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5,0,0);&lt;br /&gt;
glTranslatef(0, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Dies hat bewirkt, dass sich unser Zeichenstift 1,5 Einheiten nach links (negativer Bereich der X-Achse) und anschließend 6Einheiten nach hinten bewegt hat. Ich habe diesen Fall absichtlich in zwei Schritten gefasst, um es zu verdeutlichen. Sicherlich wäre es einfacher, alles mit nur einem Aufruf von [[glTranslate|glTranslate*]] zu machen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Man beachte, dass in diesem Fall die 6 Schritte nach hinten notwendig sind um ein bisschen Distanz zum Objekt zu bekommen und nicht direkt in ihm zu stehen!&lt;br /&gt;
&lt;br /&gt;
Fertig! Schon haben wir dort unseren &amp;quot;Zeichenstift&amp;quot; positioniert, der nun auf weitere Zeichenkommandos von uns wartet. Das mag sicherlich alles ein wenig verwirrend klingen testet es am Besten aus und spielt mit den Parametern und erkennt, was gemeint ist :).&lt;br /&gt;
== Von Sichtungen... ==&lt;br /&gt;
=== Die Büchse der Pandora ===&lt;br /&gt;
Nun sind wir aber auch alle scharf darauf, endlich etwas zu rendern und auf dem Bildschirm auszugeben. Dies geschieht z.B. mit folgenden Zeilen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
  glVertex3f(-1,-1, 0);&lt;br /&gt;
  glVertex3f( 0, 1, 0);&lt;br /&gt;
  glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wir erkennen hierbei eindeutig eine Art Block. Gerade wir Pascaler sollten diese ja lieben :-&amp;gt;. Wir teilen OpenGL mit Hilfe von [[glBegin]] mit, dass wir ein Objekt zeichnen wollen. In diesem Fall übergeben wir den Parameter GL_TRIANGLE, der OpenGL angibt, dass folgende Punkte als ein Dreieck interpretiert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Anschließend folgt ein dreifacher Aufruf von [[glVertex|glVertex3f]]. Jeder Aufruf erzeugt nun einen Punkt (Vertex) in unserem 3D-Raum. Da wir OpenGL bei glBegin mitgeteilt haben, dass diese Punkte zu einem Dreieck zusammengefügt werden sollen wird das auch so getan ;).&lt;br /&gt;
&lt;br /&gt;
Wie wir auf dem Bild erkennen können, wurde unser Dreieck wie erwartet nach links verschoben abgebildet und auch mit einem leichten Abstand zur Kamera, nämlich 6 Einheiten entlang der Z-Achse.&lt;br /&gt;
=== Guter Stoff! ===&lt;br /&gt;
Nun ... ein wenig trostlos sieht unser Dreieck nun doch aus, oder? Ich habe übrigens damals bei D3D rund eine Woche benötigt, bis ich ein schwarzes Dreieck hatte. Wir haben immerhin schon ein weißes ... aber wir gehen nun einen Schritt weiter und werden das Dreieck schön bunt einfärben.&lt;br /&gt;
&lt;br /&gt;
Bevor nun irgendjemand anfängt und Pixel für Pixel den Bildschirm nach zu pinseln oder gar sein PaintShop bereits offen hat, um die ersten Texturen zu erstellen, sei gestoppt! Es gibt für einfache Einfärbungen in OpenGL eine bessere Methode. Wir definieren einfach für jeden Eckpunkt eine Farbe und OpenGL wird dann sogar eigenständig die Farbverläufe dafür erstellen. Jeder der D3D kennt, wird diese Vorgehensweise bekannt vorkommen und er wird beginnen verzweifelt nach dem FVF zu suchen, um es korrekt zu definieren... Wenn Ihr einen Vertex zeichnet, so rendert OpenGL diesen automatisch &amp;quot;weiß&amp;quot; (Ah huch! Deswegen ist unser Dreieck auch weiß???). Alles was wir nun machen müssen, ist OpenGL mitzuteilen, dass es eine andere Farbe einsetzen soll. Und zwar wird OpenGL diese Farbe für alle folgenden Eckpunkte nutzen, so lange bis von uns ein anderes Kommando kommt.&lt;br /&gt;
&lt;br /&gt;
Der mysteriöse Befehl, um den ich nun schon die ganze Zeit herumschwafle ist [[glColor|glColor*]]:&lt;br /&gt;
&amp;lt;pascal&amp;gt;// Alle folgenden Eckpunkte werden rot gefärbt&lt;br /&gt;
glColor3f(1,0,0);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wobei jeder Parameter einen Farbwert repräsentiert und zwar nach dem Muster RGB. Es wird ein Wert zwischen 1 und 0 erwartet, wobei eine Eins &amp;quot;volle Farbsättigung&amp;quot; bedeutet. Das heißt in unserem Fall haben wir als Farbe &amp;quot;rot&amp;quot; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Und weil wir schließlich die Welt ein wenig bunter machen und nicht nur das weiße Dreieck rot färben wollten, werden wir nach jedem Eckpunkt eine neue Farbe setzen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
  glColor3f(1, 0, 0); glVertex3f(-1,-1, 0);&lt;br /&gt;
  glColor3f(0, 1, 0); glVertex3f( 0, 1, 0);&lt;br /&gt;
  glColor3f(0, 0, 1); glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Und dies ist dann unser farbenfrohes Ergebnis. Beeindruckend, wenn man bedenkt, wie wenig Aufwand letztendlich dahinter steckt, oder?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_dreieck.gif]]&lt;br /&gt;
&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Wer meine Tutorials kennt weiß, dass zum Abschluß noch immer ein wenig Geblubber von mir kommt (man beachte diese entzückende Wortwahl von meiner einer hoffe, der Lektor findet es auch amüsant). (Anm. des Lektors: Und wie!) Schauen wir doch mal stolz auf das zurück, was wir heute erreicht haben! Wir haben OpenGL initialisiert, ein erstes Dreieck auf den Bildschirm gezaubert und dieses in den Farbtopf gesteckt! Das solltet Ihr als ein historisches Ereignis ansehen. Als ich damals mit D3D angefangen habe, brauchte ich, um es mir selbst zu erarbeiten, ca. eine Woche (Das ist jetzt der Moment, in dem Ihr Eure Hände heben solltest und ein lautes &amp;quot;Call me God&amp;quot; aus Euch herauskommen sollte, so dass zumindest Eure unmittelbaren Mitmenschen denken, dass Ihr einen Dachschaden habt!!! Das gehört einfach mit dazu ^__- )&lt;br /&gt;
&lt;br /&gt;
Wie immer solltet Ihr Euch nun hinsetzen und Euch ein wenig mit den Parametern vertraut machen. Speziell bei glTranslate* solltet Ihr ein wenig mit den Parametern experimentieren, damit Ihr seht, was es mit den Matrizen auf sich hat und wie diese funktionieren. Wenn Ihr dann auch denkt, dass Ihr damit vertraut seid, versucht ein wenig mit den einzelnen Vertexpositionen zu experimentieren und verändert diese. Wenn auch das klar ist, setzt Euch in die Ecke und warte sehnsüchtig auf mehr von uns :D! (Anm: die &amp;quot;Ecke&amp;quot; ist nicht die Kneipe nebenan ... :)&lt;br /&gt;
&lt;br /&gt;
Im nächsten Kapitel werden wir dann Matrizen-Hardcore machen ... legt also schon mal Euer Aspirin parat, es wird witzig werden *grunz* :).&lt;br /&gt;
&lt;br /&gt;
Und wie immer freuen wir uns sehr über Feedback. Schreibt uns doch einfach, sagt was Ihr gut und was hingegen Ihr als schlecht empfunden habt! Auch freuen wir uns immer über Ideen für weitere Tutorials, teilt uns also bitte Eure Ideen mit ;)!&lt;br /&gt;
&lt;br /&gt;
Okay ich wünsche Euch einen angenehmen Tag / Nacht!&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_lektion3_skalierung.gif&amp;diff=12901</id>
		<title>Datei:Tutimg lektion3 skalierung.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_lektion3_skalierung.gif&amp;diff=12901"/>
				<updated>2005-05-02T16:15:00Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: Drei Dreiecke, die entsprechend skaliert wurden&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Drei Dreiecke, die entsprechend skaliert wurden&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=7483</id>
		<title>Tutorial Lektion 2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=7483"/>
				<updated>2005-05-02T16:11:57Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Entdeckung einer neuen Welt =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Ich möchte Euch an dieser Stelle bei DGL herzlich willkommen heißen. Vermutlich wird dies eines der ersten Tutorials sein, das Ihr als Einsteiger lesen werdet. Wahrscheinlich werdet Ihr dann auch noch nicht lange bei uns sein und Euch nicht vorstellen können, dass all die Schreiber auf unserer Seite keine Gurus, sondern ganz normale Menschen sind.&lt;br /&gt;
&lt;br /&gt;
Man kann uns also jeder Zeit im Forum anfassen, uns Fragen stellen, Vorschläge unterbreiten oder einfach nur einmal kurz mit einem Lob ermutigen weitere Texte zu verfassen ;-).&lt;br /&gt;
&lt;br /&gt;
Ich wünsche Euch an dieser Stelle viel Erfolg bei dem Einstieg in die Thematik OpenGL und ermahne Euch noch einmal, dass Ihr Eure Ziele nicht zu weit steckt. Wirklich Spaß beginnt OpenGL nämlich erst dann zu machen, wenn man stets kleinere Erfolge feiern kann.&lt;br /&gt;
== Höhere Mächte - Matrizen und ihre Folgen ==&lt;br /&gt;
=== Saubere Arbeit ===&lt;br /&gt;
Bevor wir direkt beginnen etwas zu Zeichnen müssen wir erst einmal das Bild löschen, denn wie in der vorherigen Lektion beschrieben zeichnen wir die Szene jeden Schleifendurchlauf neu. Das Löschen der Puffer, in dem die Bildinformationen enthalten sind übernimmt die Funktion [[glClear]]. Die Farbinformationen unser  [[Fragment|Fragmente]] (Fragmente sind vergleichbar mit den [[Pixel|Pixeln]] auf dem Bildschirm besitzen aber weitere Informationen wie z.B. Tiefenwerte. Bei der Ausgabe des Bildes werden diese Fragmente in Pixel umgewandelt) sind in dem so genannten [[Farbpuffer]] (Colorbuffer) gespeichert. Aus diesem Grund übergeben wir an die Funktion glClear die Konstante GL_COLOR_BUFFER_BIT.&lt;br /&gt;
&amp;lt;pascal&amp;gt;//Farbbuffer entleeren&lt;br /&gt;
glClear(GL_COLOR_BUFFER_BIT);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Mit Hilfe des Befehls [[glClearColor]] können wir festlegen, welche Farbinformationen mit dem Aufruf von glClear in den Colorbuffer geschrieben werden sollen. Wenn wir es also genau nehmen so löscht glClear den Colorbuffer nicht, sondern es schreibt ihn mit den definierten Werten voll. Standardmäßig erhalten die Fragmente eine schwarze Farbe.&lt;br /&gt;
&lt;br /&gt;
Es wird also nicht bei jedem Zeichenvorgang (Rendervorgang) der Bildspeicher gelöscht, sondern der Programmierer entscheidet, wann dies geschehen soll. Theoretisch könnt Ihr auch die Szene wiedergeben und dann löschen, bevor sie ausgegeben wird... wer's mag :).&lt;br /&gt;
&lt;br /&gt;
Wer sich entscheidet den Colorbuffer nicht zu löschen, der kann so auch einige nette Effekte erzeugen. Den Cheatern unter euch sollte der erreichte Effekt bekannt vorkommen, wenn man beispielsweise bei Counter-Strike durch die Wand gelaufen ist. Der Grund für das Verwischen ist in beiden Fällen derselbe: Das neue Bild wird gezeichnet, ohne dass das alte Bild aus dem Puffer entfernt wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_puffereffekt.gif]]&lt;br /&gt;
&lt;br /&gt;
=== Und die Welt ist doch keine Scheibe ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_koordinatensystem.gif]]&lt;br /&gt;
&lt;br /&gt;
Nachdem wir nun wieder Ordnung im Speicher geschafft haben, können wir zum interessanten Teil kommen: &amp;quot;Wie darf man sich einen 3D-Raum vorstellen?&amp;quot; Nun  warum schaut Ihr Euch nicht einmal in Eurem Zimmer um?&lt;br /&gt;
&lt;br /&gt;
Versuchen wir doch mal, ein Beispiel direkt aus dem Leben gegriffen zu nehmen und stellen uns unsere Umgebung als Koordinaten-System vor (Igitt!). Der Monitor, der hoffentlich direkt vor uns steht, ist in diesem Fall unser Ursprung, d.h. er liegt an dem Punkt (0, 0, 0).&lt;br /&gt;
&lt;br /&gt;
Blicken wir seitwärts neben den Monitor, so sehen wir eine Linie (wenn Ihr es nicht tun solltest, macht Euch keine Sorgen  solche Anfälle hat der Autor häufiger *g*), die von links nach rechts verläuft. Es handelt sich hierbei um die X-Achse, die links vom Monitor im negativen Bereich verläuft, rechts davon in den positiven.&lt;br /&gt;
&lt;br /&gt;
Nun blicken wir einmal nach oben und einmal nach unten und schon erspähen wir die Y-Achse, die oberhalb des Monitors positiv verläuft, unterhalb negativ. Wunderbar! Wenn Ihr bereits in 2D gearbeitet habt, solltet Ihr an dieser Stelle ein dümmliches Grinsen auf Eurem Gesichte haben und das wohltuenden Gefühl, dass Euch das doch alles bereits irgendwie bekannt vorkommt. Doch zu unserem Entsetzen können wir uns ja auch noch von unserem Bildschirm wegbewegen oder auch dichter heran (alle Kurzsichtigen unter uns sollten das nicht so persönlich nehmen, auch Sie leben in einem 3D-Raum ^__-).&lt;br /&gt;
&lt;br /&gt;
Dieses Phänomen ist im 3D-Raum typisch, jedoch nicht unerklärlich, da wir uns auf der Z-Achse bewegen. Rollen wir mit dem Stuhl vom Monitor weg, so gelangen wir in den positiven Bereich der Z-Achse, bewegen wir uns drauf zu, gelangen wir in den negativen Bereich. Jeder, der bereits in D3D programmiert hat, sollte sich schleunigst einprägen, dass das ein großer Unterschied zwischen D3D und OpenGL ist. Das kann sonst zu einigen wirklich fiesen Fehlern führen, wenn man es nicht weiß *fg*.&lt;br /&gt;
&lt;br /&gt;
Soweit so gut! Klingt bisher hoffentlich immer noch nicht so kompliziert. Nur keine Sorge, das Niveau versuchen wir zu halten ;).&lt;br /&gt;
&lt;br /&gt;
Speziell wenn Ihr bereits 2D-Spiele programmiert habt, solltet Ihr Euch sehr schnell von folgenden Gedanken trennen: Die Koordinaten, die Ihr seht und angebt, entsprechen in der Regel nicht den Pixeln des Bildschirmes, sondern so genannten Weltkoordinaten. Eine Definition für diese Weltkoordinaten gibt es nicht, denn wie groß diese sind ist dem Programmierer überlassen. Ob Ihr euer Objekt eine Einheit vor Euch und 0,1 Einheit rechts von Euch oder aber 100 Einheiten vor euch und 10 Einheiten neben Euch positioniert ist egal. Die euch zur Verfügung stehende Welt ist grenzenlos ;). Ihr könnt Eure Szene theoretisch unendlich klein oder aber unendlich groß darstellen. Das einzige was euch wirklich daran hindert ist die Größe und Auflösung der Euch zur Verfügung stehenden Typen wie Integer oder Single ;). Der eigentliche Größeneindruck eines Objektes entsteht durch die Geschwindigkeit mit der sich der Betrachter und andere Objekte in der Welt bewegen.&lt;br /&gt;
=== Der erste Kontakt ===&lt;br /&gt;
Um nun etwas mit OpenGL rendern zu können, müssen wir uns bewusst werden, was die Worldmatrix ist. In dieser Matrix wird festgehalten, wie und wo ein Objekt gezeichnet wird. Das hört sich vielleicht zunächst recht merkwürdig an, lässt sich aber leicht veranschaulichen.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns vor, die Worldmatrix zeigt auf einen Punkt, an dem ein Objekt gezeichnet werden soll (ganz übel wir werden später detaillierter darauf eingehen. Sollte es jemand also nach der folgenden Erläuterung nicht verstanden haben, kann er mich selbstverständlich persönlich per Mail zur &amp;quot;Rechenschaft&amp;quot; ziehen oder aber er wirft einen Blick in unser OpenGLWiki :)).&lt;br /&gt;
&lt;br /&gt;
Diesen Punkt setzen wir nun am Anfang in den Mittelpunkt unseres Koordinatensystems. Um oberes Beispiel aufzugreifen: Den Bildschirm. Dies geschieht mit dem Befehl [[glLoadIdentity]] und entspricht einem Reset der Worldmatrix. Theoretisch können wir nun an dieser Stelle etwas zeichnen. Dies würde allerdings dazu führen, dass das Objekt sehr groß oder gar nicht zu sehen ist, weil wir uns eben auch an diesen Stellen befinden. Gehen wir doch einmal 1,5 Einheiten nach links und 6 Einheiten nach hinten!&lt;br /&gt;
&lt;br /&gt;
Hierfür sollte man sich bewusst werden, dass wir in OpenGL praktisch an einem Stuhl gefesselt sind, d.h. wir können uns gar nicht bewegen. Das soll uns aber nicht davon abhalten. Wir brauchen ja nur die ganze Welt so zu bewegen, dass es für uns aussieht, als ob wir uns bewegen. Denn wenn sich alles außer uns nach links bewegt, haben wir den Eindruck, wir wären nach rechts gewandert, right?&lt;br /&gt;
&lt;br /&gt;
Nun aber zu der Bewegung unseres ersten Objektes:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5,0,0);&lt;br /&gt;
glTranslatef(0, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Dies hat bewirkt, dass sich unser Zeichenstift 1,5 Einheiten nach links (negativer Bereich der X-Achse) und anschließend 6Einheiten nach hinten bewegt hat. Ich habe diesen Fall absichtlich in zwei Schritten gefasst, um es zu verdeutlichen. Sicherlich wäre es einfacher, alles mit nur einem Aufruf von [[glTranslate|glTranslate*]] zu machen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Man beachte, dass in diesem Fall die 6 Schritte nach hinten notwendig sind um ein bisschen Distanz zum Objekt zu bekommen und nicht direkt in ihm zu stehen!&lt;br /&gt;
&lt;br /&gt;
Fertig! Schon haben wir dort unseren &amp;quot;Zeichenstift&amp;quot; positioniert, der nun auf weitere Zeichenkommandos von uns wartet. Das mag sicherlich alles ein wenig verwirrend klingen testet es am Besten aus und spielt mit den Parametern und erkennt, was gemeint ist :).&lt;br /&gt;
== Von Sichtungen... ==&lt;br /&gt;
=== Die Büchse der Pandora ===&lt;br /&gt;
Nun sind wir aber auch alle scharf darauf, endlich etwas zu rendern und auf dem Bildschirm auszugeben. Dies geschieht z.B. mit folgenden Zeilen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
  glVertex3f(-1,-1, 0);&lt;br /&gt;
  glVertex3f( 0, 1, 0);&lt;br /&gt;
  glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wir erkennen hierbei eindeutig eine Art Block. Gerade wir Pascaler sollten diese ja lieben :-&amp;gt;. Wir teilen OpenGL mit Hilfe von [[glBegin]] mit, dass wir ein Objekt zeichnen wollen. In diesem Fall übergeben wir den Parameter GL_TRIANGLE, der OpenGL angibt, dass folgende Punkte als ein Dreieck interpretiert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Anschließend folgt ein dreifacher Aufruf von [[glVertex|glVertex3f]]. Jeder Aufruf erzeugt nun einen Punkt (Vertex) in unserem 3D-Raum. Da wir OpenGL bei glBegin mitgeteilt haben, dass diese Punkte zu einem Dreieck zusammengefügt werden sollen wird das auch so getan ;).&lt;br /&gt;
&lt;br /&gt;
Wie wir auf dem Bild erkennen können, wurde unser Dreieck wie erwartet nach links verschoben abgebildet und auch mit einem leichten Abstand zur Kamera, nämlich 6 Einheiten entlang der Z-Achse.&lt;br /&gt;
=== Guter Stoff! ===&lt;br /&gt;
Nun ... ein wenig trostlos sieht unser Dreieck nun doch aus, oder? Ich habe übrigens damals bei D3D rund eine Woche benötigt, bis ich ein schwarzes Dreieck hatte. Wir haben immerhin schon ein weißes ... aber wir gehen nun einen Schritt weiter und werden das Dreieck schön bunt einfärben.&lt;br /&gt;
&lt;br /&gt;
Bevor nun irgendjemand anfängt und Pixel für Pixel den Bildschirm nach zu pinseln oder gar sein PaintShop bereits offen hat, um die ersten Texturen zu erstellen, sei gestoppt! Es gibt für einfache Einfärbungen in OpenGL eine bessere Methode. Wir definieren einfach für jeden Eckpunkt eine Farbe und OpenGL wird dann sogar eigenständig die Farbverläufe dafür erstellen. Jeder der D3D kennt, wird diese Vorgehensweise bekannt vorkommen und er wird beginnen verzweifelt nach dem FVF zu suchen, um es korrekt zu definieren... Wenn Ihr einen Vertex zeichnet, so rendert OpenGL diesen automatisch &amp;quot;weiß&amp;quot; (Ah huch! Deswegen ist unser Dreieck auch weiß???). Alles was wir nun machen müssen, ist OpenGL mitzuteilen, dass es eine andere Farbe einsetzen soll. Und zwar wird OpenGL diese Farbe für alle folgenden Eckpunkte nutzen, so lange bis von uns ein anderes Kommando kommt.&lt;br /&gt;
&lt;br /&gt;
Der mysteriöse Befehl, um den ich nun schon die ganze Zeit herumschwafle ist [[glColor|glColor*]]:&lt;br /&gt;
&amp;lt;pascal&amp;gt;// Alle folgenden Eckpunkte werden rot gefärbt&lt;br /&gt;
glColor3f(1,0,0);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wobei jeder Parameter einen Farbwert repräsentiert und zwar nach dem Muster RGB. Es wird ein Wert zwischen 1 und 0 erwartet, wobei eine Eins &amp;quot;volle Farbsättigung&amp;quot; bedeutet. Das heißt in unserem Fall haben wir als Farbe &amp;quot;rot&amp;quot; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Und weil wir schließlich die Welt ein wenig bunter machen und nicht nur das weiße Dreieck rot färben wollten, werden wir nach jedem Eckpunkt eine neue Farbe setzen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
  glColor3f(1, 0, 0); glVertex3f(-1,-1, 0);&lt;br /&gt;
  glColor3f(0, 1, 0); glVertex3f( 0, 1, 0);&lt;br /&gt;
  glColor3f(0, 0, 1); glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Und dies ist dann unser farbenfrohes Ergebnis. Beeindruckend, wenn man bedenkt, wie wenig Aufwand letztendlich dahinter steckt, oder?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_dreieck.gif]]&lt;br /&gt;
&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Wer meine Tutorials kennt weiß, dass zum Abschluß noch immer ein wenig Geblubber von mir kommt (man beachte diese entzückende Wortwahl von meiner einer hoffe, der Lektor findet es auch amüsant). (Anm. des Lektors: Und wie!) Schauen wir doch mal stolz auf das zurück, was wir heute erreicht haben! Wir haben OpenGL initialisiert, ein erstes Dreieck auf den Bildschirm gezaubert und dieses in den Farbtopf gesteckt! Das solltet Ihr als ein historisches Ereignis ansehen. Als ich damals mit D3D angefangen habe, brauchte ich, um es mir selbst zu erarbeiten, ca. eine Woche (Das ist jetzt der Moment, in dem Ihr Eure Hände heben solltest und ein lautes &amp;quot;Call me God&amp;quot; aus Euch herauskommen sollte, so dass zumindest Eure unmittelbaren Mitmenschen denken, dass Ihr einen Dachschaden habt!!! Das gehört einfach mit dazu ^__- )&lt;br /&gt;
&lt;br /&gt;
Wie immer solltet Ihr Euch nun hinsetzen und Euch ein wenig mit den Parametern vertraut machen. Speziell bei glTranslate* solltet Ihr ein wenig mit den Parametern experimentieren, damit Ihr seht, was es mit den Matrizen auf sich hat und wie diese funktionieren. Wenn Ihr dann auch denkt, dass Ihr damit vertraut seid, versucht ein wenig mit den einzelnen Vertexpositionen zu experimentieren und verändert diese. Wenn auch das klar ist, setzt Euch in die Ecke und warte sehnsüchtig auf mehr von uns :D! (Anm: die &amp;quot;Ecke&amp;quot; ist nicht die Kneipe nebenan ... :)&lt;br /&gt;
&lt;br /&gt;
Im nächsten Kapitel werden wir dann Matrizen-Hardcore machen ... legt also schon mal Euer Aspirin parat, es wird witzig werden *grunz* :).&lt;br /&gt;
&lt;br /&gt;
Und wie immer freuen wir uns sehr über Feedback. Schreibt uns doch einfach, sagt was Ihr gut und was hingegen Ihr als schlecht empfunden habt! Auch freuen wir uns immer über Ideen für weitere Tutorials, teilt uns also bitte Eure Ideen mit ;)!&lt;br /&gt;
&lt;br /&gt;
Okay ich wünsche Euch einen angenehmen Tag / Nacht!&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=7482</id>
		<title>Tutorial Lektion 2</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Tutorial_Lektion_2&amp;diff=7482"/>
				<updated>2005-04-28T09:21:09Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Entdeckung einer neuen Welt =&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Ich möchte Euch an dieser Stelle bei DGL herzlich willkommen heißen. Vermutlich wird dies eines der ersten Tutorials sein, das Ihr als Einsteiger lesen werdet. Wahrscheinlich werdet Ihr dann auch noch nicht lange bei uns sein und Euch nicht vorstellen können, dass all die Schreiber auf unserer Seite keine Gurus, sondern ganz normale Menschen sind.&lt;br /&gt;
&lt;br /&gt;
Man kann uns also jeder Zeit im Forum anfassen, uns Fragen stellen, Vorschläge unterbreiten oder einfach nur einmal kurz mit einem Lob ermutigen weitere Texte zu verfassen ;-).&lt;br /&gt;
&lt;br /&gt;
Ich wünsche Euch an dieser Stelle viel Erfolg bei dem Einstieg in die Thematik OpenGL und ermahne Euch noch einmal, dass Ihr Eure Ziele nicht zu weit steckt. Wirklich Spaß beginnt OpenGL nämlich erst dann zu machen, wenn man stets kleinere Erfolge feiern kann.&lt;br /&gt;
== Höhere Mächte - Matrizen und ihre Folgen ==&lt;br /&gt;
=== Saubere Arbeit ===&lt;br /&gt;
Bevor wir direkt beginnen etwas zu Zeichnen müssen wir erst einmal das Bild löschen, denn wie in der vorherigen Lektion beschrieben zeichnen wir die Szene jeden Schleifendurchlauf neu. Das Löschen der Puffer, in dem die Bildinformationen enthalten sind übernimmt die Funktion [[glClear]]. Die Farbinformationen unser  [[Fragment|Fragmente]] (Fragmente sind vergleichbar mit den Pixeln auf dem Bildschirm besitzen aber weitere Informationen wie z.B. Tiefenwerte. Bei der Ausgabe des Bildes werden diese Fragmente in Pixel umgewandelt) sind in dem so genannten [[Farbpuffer]] (Colorbuffer) gespeichert. Aus diesem Grund übergeben wir an die Funktion glClear die Konstante GL_COLOR_BUFFER_BIT.&lt;br /&gt;
&amp;lt;pascal&amp;gt;//Farbbuffer entleeren&lt;br /&gt;
glClear(GL_COLOR_BUFFER_BIT);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Mit Hilfe des Befehls [[glClearColor]] können wir festlegen, welche Farbinformationen mit dem Aufruf von glClear in den Colorbuffer geschrieben werden sollen. Wenn wir es also genau nehmen so löscht glClear den Colorbuffer nicht, sondern es schreibt ihn mit den definierten Werten voll. Standardmäßig erhalten die Fragmente eine schwarze Farbe.&lt;br /&gt;
&lt;br /&gt;
Es wird also nicht bei jedem Zeichenvorgang (Rendervorgang) der Bildspeicher gelöscht, sondern der Programmierer entscheidet, wann dies geschehen soll. Theoretisch könnt Ihr auch die Szene wiedergeben und dann löschen, bevor sie ausgegeben wird... wer's mag :).&lt;br /&gt;
&lt;br /&gt;
Wer sich entscheidet den Colorbuffer nicht zu löschen, der kann so auch einige nette Effekte erzeugen. Den Cheatern unter euch sollte der erreichte Effekt bekannt vorkommen, wenn man beispielsweise bei Counter-Strike durch die Wand gelaufen ist. Der Grund für das Verwischen ist in beiden Fällen derselbe: Das neue Bild wird gezeichnet, ohne dass das alte Bild aus dem Puffer entfernt wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_puffereffekt.gif]]&lt;br /&gt;
&lt;br /&gt;
=== Und die Welt ist doch keine Scheibe ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_koordinatensystem.gif]]&lt;br /&gt;
&lt;br /&gt;
Nachdem wir nun wieder Ordnung im Speicher geschafft haben, können wir zum interessanten Teil kommen: &amp;quot;Wie darf man sich einen 3D-Raum vorstellen?&amp;quot; Nun  warum schaut Ihr Euch nicht einmal in Eurem Zimmer um?&lt;br /&gt;
&lt;br /&gt;
Versuchen wir doch mal, ein Beispiel direkt aus dem Leben gegriffen zu nehmen und stellen uns unsere Umgebung als Koordinaten-System vor (Igitt!). Der Monitor, der hoffentlich direkt vor uns steht, ist in diesem Fall unser Ursprung, d.h. er liegt an dem Punkt (0, 0, 0).&lt;br /&gt;
&lt;br /&gt;
Blicken wir seitwärts neben den Monitor, so sehen wir eine Linie (wenn Ihr es nicht tun solltest, macht Euch keine Sorgen  solche Anfälle hat der Autor häufiger *g*), die von links nach rechts verläuft. Es handelt sich hierbei um die X-Achse, die links vom Monitor im negativen Bereich verläuft, rechts davon in den positiven.&lt;br /&gt;
&lt;br /&gt;
Nun blicken wir einmal nach oben und einmal nach unten und schon erspähen wir die Y-Achse, die oberhalb des Monitors positiv verläuft, unterhalb negativ. Wunderbar! Wenn Ihr bereits in 2D gearbeitet habt, solltet Ihr an dieser Stelle ein dümmliches Grinsen auf Eurem Gesichte haben und das wohltuenden Gefühl, dass Euch das doch alles bereits irgendwie bekannt vorkommt. Doch zu unserem Entsetzen können wir uns ja auch noch von unserem Bildschirm wegbewegen oder auch dichter heran (alle Kurzsichtigen unter uns sollten das nicht so persönlich nehmen, auch Sie leben in einem 3D-Raum ^__-).&lt;br /&gt;
&lt;br /&gt;
Dieses Phänomen ist im 3D-Raum typisch, jedoch nicht unerklärlich, da wir uns auf der Z-Achse bewegen. Rollen wir mit dem Stuhl vom Monitor weg, so gelangen wir in den positiven Bereich der Z-Achse, bewegen wir uns drauf zu, gelangen wir in den negativen Bereich. Jeder, der bereits in D3D programmiert hat, sollte sich schleunigst einprägen, dass das ein großer Unterschied zwischen D3D und OpenGL ist. Das kann sonst zu einigen wirklich fiesen Fehlern führen, wenn man es nicht weiß *fg*.&lt;br /&gt;
&lt;br /&gt;
Soweit so gut! Klingt bisher hoffentlich immer noch nicht so kompliziert. Nur keine Sorge, das Niveau versuchen wir zu halten ;).&lt;br /&gt;
&lt;br /&gt;
Speziell wenn Ihr bereits 2D-Spiele programmiert habt, solltet Ihr Euch sehr schnell von folgenden Gedanken trennen: Die Koordinaten, die Ihr seht und angebt, entsprechen in der Regel nicht den Pixeln des Bildschirmes, sondern so genannten Weltkoordinaten. Eine Definition für diese Weltkoordinaten gibt es nicht, denn wie groß diese sind ist dem Programmierer überlassen. Ob Ihr euer Objekt eine Einheit vor Euch und 0,1 Einheit rechts von Euch oder aber 100 Einheiten vor euch und 10 Einheiten neben Euch positioniert ist egal. Die euch zur Verfügung stehende Welt ist grenzenlos ;). Ihr könnt Eure Szene theoretisch unendlich klein oder aber unendlich groß darstellen. Das einzige was euch wirklich daran hindert ist die Größe und Auflösung der Euch zur Verfügung stehenden Typen wie Integer oder Single ;). Der eigentliche Größeneindruck eines Objektes entsteht durch die Geschwindigkeit mit der sich der Betrachter und andere Objekte in der Welt bewegen.&lt;br /&gt;
=== Der erste Kontakt ===&lt;br /&gt;
Um nun etwas mit OpenGL rendern zu können, müssen wir uns bewusst werden, was die Worldmatrix ist. In dieser Matrix wird festgehalten, wie und wo ein Objekt gezeichnet wird. Das hört sich vielleicht zunächst recht merkwürdig an, lässt sich aber leicht veranschaulichen.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns vor, die Worldmatrix zeigt auf einen Punkt, an dem ein Objekt gezeichnet werden soll (ganz übel wir werden später detaillierter darauf eingehen. Sollte es jemand also nach der folgenden Erläuterung nicht verstanden haben, kann er mich selbstverständlich persönlich per Mail zur &amp;quot;Rechenschaft&amp;quot; ziehen oder aber er wirft einen Blick in unser OpenGLWiki :)).&lt;br /&gt;
&lt;br /&gt;
Diesen Punkt setzen wir nun am Anfang in den Mittelpunkt unseres Koordinatensystems. Um oberes Beispiel aufzugreifen: Den Bildschirm. Dies geschieht mit dem Befehl [[glLoadIdentity]] und entspricht einem Reset der Worldmatrix. Theoretisch können wir nun an dieser Stelle etwas zeichnen. Dies würde allerdings dazu führen, dass das Objekt sehr groß oder gar nicht zu sehen ist, weil wir uns eben auch an diesen Stellen befinden. Gehen wir doch einmal 1,5 Einheiten nach links und 6 Einheiten nach hinten!&lt;br /&gt;
&lt;br /&gt;
Hierfür sollte man sich bewusst werden, dass wir in OpenGL praktisch an einem Stuhl gefesselt sind, d.h. wir können uns gar nicht bewegen. Das soll uns aber nicht davon abhalten. Wir brauchen ja nur die ganze Welt so zu bewegen, dass es für uns aussieht, als ob wir uns bewegen. Denn wenn sich alles außer uns nach links bewegt, haben wir den Eindruck, wir wären nach rechts gewandert, right?&lt;br /&gt;
&lt;br /&gt;
Nun aber zu der Bewegung unseres ersten Objektes:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5,0,0);&lt;br /&gt;
glTranslatef(0, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Dies hat bewirkt, dass sich unser Zeichenstift 1,5 Einheiten nach links (negativer Bereich der X-Achse) und anschließend 6Einheiten nach hinten bewegt hat. Ich habe diesen Fall absichtlich in zwei Schritten gefasst, um es zu verdeutlichen. Sicherlich wäre es einfacher, alles in einem Schritt zu machen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glTranslatef(-1.5, 0,-6);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Man beachte, dass in diesem Fall die 6 Schritte nach hinten notwendig sind um ein bisschen Distanz zum Objekt zu bekommen und nicht direkt in ihm zu stehen!&lt;br /&gt;
&lt;br /&gt;
Fertig! Schon haben wir dort unseren &amp;quot;Zeichenstift&amp;quot; positioniert, der nun auf weitere Zeichenkommandos von uns wartet. Das mag sicherlich alles ein wenig verwirrend klingen testet es am Besten aus und spielt mit den Parametern und erkennt, was gemeint ist :).&lt;br /&gt;
== Von Sichtungen... ==&lt;br /&gt;
=== Die Büchse der Pandora ===&lt;br /&gt;
Nun sind wir aber auch alle scharf darauf, endlich etwas zu rendern und auf dem Bildschirm auszugeben. Dies geschieht z.B. mit folgenden Zeilen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
glVertex3f(-1,-1, 0);&lt;br /&gt;
glVertex3f( 0, 1, 0);&lt;br /&gt;
glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wir erkennen hierbei eindeutig eine Art Block. Gerade wir Pascaler sollten diese ja lieben :-&amp;gt;. Wir teilen OpenGL mit Hilfe von [[glBegin]] mit, dass wir ein Objekt zeichnen wollen. In diesem Fall übergeben wir den Parameter GL_TRIANGLE, der OpenGL angibt, dass folgende Punkte als ein Dreieck interpretiert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Anschließend folgt ein dreifacher Aufruf von [[glVertex|glVertex3f]]. Jeder Aufruf erzeugt nun einen Punkt (Vertex) in unserem 3D-Raum. Da wir OpenGL bei glBegin mitgeteilt haben, dass diese Punkte zu einem Dreieck zusammengefügt werden sollen wird das auch so getan ;).&lt;br /&gt;
&lt;br /&gt;
Wie wir auf dem Bild erkennen können, wurde unser Dreieck wie erwartet nach links verschoben abgebildet und auch mit einem leichten Abstand zur Kamera, nämlich 6 Einheiten entlang der Z-Achse.&lt;br /&gt;
=== Guter Stoff! ===&lt;br /&gt;
Nun ... ein wenig trostlos sieht unser Dreieck nun doch aus, oder? Ich habe übrigens damals bei D3D rund eine Woche benötigt, bis ich ein schwarzes Dreieck hatte. Wir haben immerhin schon ein weißes ... aber wir gehen nun einen Schritt weiter und werden das Dreieck schön bunt einfärben.&lt;br /&gt;
&lt;br /&gt;
Bevor nun irgendjemand anfängt und Pixel für Pixel den Bildschirm nach zu pinseln oder gar sein PaintShop bereits offen hat, um die ersten Texturen zu erstellen, sei gestoppt! Es gibt für einfache Einfärbungen in OpenGL eine bessere Methode. Wir definieren einfach für jeden Eckpunkt eine Farbe und OpenGL wird dann sogar eigenständig die Farbverläufe dafür erstellen. Jeder der D3D kennt, wird diese Vorgehensweise bekannt vorkommen und er wird beginnen verzweifelt nach dem FVF zu suchen, um es korrekt zu definieren... Wenn Ihr einen Vertex zeichnet, so rendert OpenGL diesen automatisch &amp;quot;weiß&amp;quot; (Ah huch! Deswegen ist unser Dreieck auch weiß???). Alles was wir nun machen müssen, ist OpenGL mitzuteilen, dass es eine andere Farbe einsetzen soll. Und zwar wird OpenGL diese Farbe für alle folgenden Eckpunkte nutzen, so lange bis von uns ein anderes Kommando kommt.&lt;br /&gt;
&lt;br /&gt;
Der mysteriöse Befehl, um den ich nun schon die ganze Zeit herumschwafle ist:&lt;br /&gt;
&amp;lt;pascal&amp;gt;// Alle folgenden Eckpunkte werden rot gefärbt&lt;br /&gt;
glColor3f(1,0,0);&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Wobei jeder Parameter einen Farbwert repräsentiert und zwar nach dem Muster RGB. Es wird ein Wert zwischen 1 und 0 erwartet, wobei eine Eins &amp;quot;volle Farbsättigung&amp;quot; bedeutet. Das heißt in unserem Fall haben wir als Farbe &amp;quot;rot&amp;quot; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Und weil wir schließlich die Welt ein wenig bunter machen und nicht nur das weiße Dreieck rot färben wollten, werden wir nach jedem Eckpunkt eine neue Farbe setzen:&lt;br /&gt;
&amp;lt;pascal&amp;gt;glBegin(GL_TRIANGLES);&lt;br /&gt;
glColor3f(1, 0, 0); glVertex3f(-1,-1, 0);&lt;br /&gt;
glColor3f(0, 1, 0); glVertex3f( 0, 1, 0);&lt;br /&gt;
glColor3f(0, 0, 1); glVertex3f( 1,-1, 0);&lt;br /&gt;
glEnd;&amp;lt;/pascal&amp;gt;&lt;br /&gt;
Und dies ist dann unser farbenfrohes Ergebnis. Beeindruckend, wenn man bedenkt, wie wenig Aufwand letztendlich dahinter steckt, oder?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[bild:tutimg_lektion2_dreieck.gif]]&lt;br /&gt;
&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
Wer meine Tutorials kennt weiß, dass zum Abschluß noch immer ein wenig Geblubber von mir kommt (man beachte diese entzückende Wortwahl von meiner einer hoffe, der Lektor findet es auch amüsant). (Anm. des Lektors: Und wie!) Schauen wir doch mal stolz auf das zurück, was wir heute erreicht haben! Wir haben OpenGL initialisiert, ein erstes Dreieck auf den Bildschirm gezaubert und dieses in den Farbtopf gesteckt! Das solltet Ihr als ein historisches Ereignis ansehen. Als ich damals mit D3D angefangen habe, brauchte ich, um es mir selbst zu erarbeiten, ca. eine Woche (Das ist jetzt der Moment, in dem Ihr Eure Hände heben solltest und ein lautes &amp;quot;Call me God&amp;quot; aus Euch herauskommen sollte, so dass zumindest Eure unmittelbaren Mitmenschen denken, dass Ihr einen Dachschaden habt!!! Das gehört einfach mit dazu ^__- )&lt;br /&gt;
&lt;br /&gt;
Wie immer solltet Ihr Euch nun hinsetzen und Euch ein wenig mit den Parametern vertraut machen. Speziell bei glTranslatef solltet Ihr ein wenig mit den Parametern experimentieren, damit Ihr seht, was es mit den Matrizen auf sich hat und wie diese funktionieren. Wenn Ihr dann auch denkt, dass Ihr damit vertraut seid, versucht ein wenig mit den einzelnen Vertexpositionen zu experimentieren und verändert diese. Wenn auch das klar ist, setzt Euch in die Ecke und warte sehnsüchtig auf mehr von uns :D! (Anm: die &amp;quot;Ecke&amp;quot; ist nicht die Kneipe nebenan ... :)&lt;br /&gt;
&lt;br /&gt;
Im nächsten Kapitel werden wir dann Matrizen-Hardcore machen ... legt also schon mal Euer Aspirin parat, es wird witzig werden *grunz* :).&lt;br /&gt;
&lt;br /&gt;
Und wie immer freuen wir uns sehr über Feedback. Schreibt uns doch einfach, sagt was Ihr gut und was hingegen Ihr als schlecht empfunden habt! Auch freuen wir uns immer über Ideen für weitere Tutorials, teilt uns also bitte Eure Ideen mit ;)!&lt;br /&gt;
&lt;br /&gt;
Okay ich wünsche Euch einen angenehmen Tag / Nacht!&lt;br /&gt;
&lt;br /&gt;
'''Euer'''&amp;lt;br&amp;gt;&lt;br /&gt;
'''Phobeus'''&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_lektion2_dreieck.gif&amp;diff=12888</id>
		<title>Datei:Tutimg lektion2 dreieck.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_lektion2_dreieck.gif&amp;diff=12888"/>
				<updated>2005-04-28T08:33:23Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: Das Ergebnis der Lektion 2&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Ergebnis der Lektion 2&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Datei:Tutimg_lektion2_puffereffekt.gif&amp;diff=12887</id>
		<title>Datei:Tutimg lektion2 puffereffekt.gif</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Datei:Tutimg_lektion2_puffereffekt.gif&amp;diff=12887"/>
				<updated>2005-04-28T08:32:26Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Effekt tritt auf, wenn man den Farbpuffer nicht vor jedem Zeichdurchgang löscht&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=glClipPlane&amp;diff=4557</id>
		<title>glClipPlane</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=glClipPlane&amp;diff=4557"/>
				<updated>2004-09-25T09:21:31Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= glClipPlane =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Name ==&lt;br /&gt;
'''glClipPlane''' - Beschreibt eine Fläche, gegen die alle Geometrie geschnitten wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 procedure '''glClipPlane'''(''plane'' : glEnum; const ''equation'' : glDouble);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;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;''plane''&amp;lt;/td&amp;gt;&lt;br /&gt;
 &amp;lt;td&amp;gt;Gibt an welche Schnittfläche positioniert werden soll. Gültig ist hier eine symbolische Konstanten '''GL_CLIP_Plane'''''i'', wobei ''i'' zwischen 0 und '''GL_MAX_CLIP_PLANES'''-1 liegen muss.&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&amp;gt;''equation''&amp;lt;/td&amp;gt;&lt;br /&gt;
 &amp;lt;td&amp;gt;Zeigt auf ein Array dass vier Fließkommawerte mit doppelter (wichtig!) Genauigkeit beinhaltet, welche als Flächenentsprechung verstanden werden.&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;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Beschreibung == &lt;br /&gt;
Die Geometrie wird immer gegen die Grenzen des aus sechs Flächen bestehenden Frustums (x,y und z) geschnitten. '''glClipPlane''' erlaubt darüber hinaus die Angabe zusätzlicher Schnittflächen, die jedoch nicht genau auf einer der drei Achsen (x,y,z) liegen müssen, gegen die die Geometrie dann auch geschnitten wird. Um festzustellen wie viele zusätzliche Schnittflächen unterstützt werden, kann man [[glGet|glGetIntegerv]] mit dem Argument '''GL_MAX_CLIP_PLANES''' aufrufen. Als Minimum muss eine Implementation sechs zusätzliche Schnittflächen unterstützen. Da die resultierende Schnittregion die Intersektion der definierten Halb-Räume darstellt, ist sie immmer konvex.&lt;br /&gt;
&lt;br /&gt;
'''glClipPlane''' beschreibt einen Halb-Raum, der eine vier-Komponenten Flächenentsprechung nutzt. Wenn '''glClipPlane''' aufgerufen wird, wird diese Entsprechung mit der inversen Modelansichtsmatrix transformiert und dann in den daraus resultierenden Betrachter-Koordinaten (&amp;quot;Aug-Raum&amp;quot;) abgelegt. Darauf folgende Änderungen an der Modelansichtsmatrix haben danach dann keinen Effekt mehr auf die abgelegten Komponenten der Flächenentsprechung. Wenn das Skalarprodukt der Betrachter-Koordinaten eines Eckpunktes und den Komponenten der Flächenentsprechung positiv oder gleich Null ist, dann liegt dieser Eckpunkt &amp;quot;in&amp;quot; dieser Schnittfläche, ansonsten nicht.&lt;br /&gt;
&lt;br /&gt;
Um Schnittflächen zu aktivieren bzw. zu deaktivieren, genügt ein Aufruf von [[glEnable]] bzw. [[glDisable]] mit dem Argument '''GL_CLIP_PLANE'''''i'', wobei ''i'' die Nummer der Schnittfläche angibt.&lt;br /&gt;
&lt;br /&gt;
In der Voreinstellung sind alle Schnittflächen als (0, 0, 0, 0) (in Betrachter-Koordinaten) definiert und deaktiviert.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Die symbolischen Konstanten für die Schnittflächen sind fortlaufend nummeriert. '''GL_CLIP_PLANE'''''i'' ist also immer gleich '''GL_CLIP_PLANE0'''+''i'';&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Fehlermeldungen ==&lt;br /&gt;
'''GL_INVALID_ENUM''' wird generiert, wenn ''plane'' kein gültiger Wert ist.&lt;br /&gt;
&lt;br /&gt;
'''GL_INVALID_OPERATION''' wird generiert, wenn '''glClipPlane''' zwischen einem [[glBegin]] und dem passenden [[glEnd]] aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==  Zugehörige Wertrückgaben ==&lt;br /&gt;
[[glGetClipPlane]]&lt;br /&gt;
[[glIsEnabled]] mit dem Token '''GL_CLIP_PLANE'''''i''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[glEnable]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:GL|ClipPlane]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Hauptseite&amp;diff=2327</id>
		<title>Hauptseite</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Hauptseite&amp;diff=2327"/>
				<updated>2004-09-14T09:24:44Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&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;
&amp;lt;div style=&amp;quot;margin: 0; margin-right:10px;  border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F8F8FF; align:right;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Willkommen im DGL Wiki!&amp;lt;/h2&amp;gt;&lt;br /&gt;
Die [http://www.delphigl.com Delphi-OpenGL-Community] hat es sich mit diesem Wiki zum Ziel gemacht eine freie Wissensdatenbank rund um das Thema [[OpenGL]] zu erschaffen, an der alle Interessierten mitwirken, oder einfach nur Wissen nachschlagen können.&lt;br /&gt;
&amp;lt;div align=&amp;quot;right&amp;quot;&amp;gt;&amp;lt;small&amp;gt;[[DGL Wiki:Willkommen|&amp;gt;&amp;gt;&amp;gt;weiter zur Willkommensseite]]&amp;lt;/small&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!-- News --&amp;gt;&lt;br /&gt;
&amp;lt;!-- ------------------------------- --&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin: 0;margin-top:5px; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F0F8FF; align:right;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;News&amp;lt;/h2&amp;gt;&lt;br /&gt;
{{Hauptseite_News}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;40%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F0F8FF;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Aktuelles&amp;lt;/h2&amp;gt;&lt;br /&gt;
[[Spezial:Statistics|{{NUMBEROFARTICLES}}]] [[Spezial:Newpages|Artikel]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Unvollständige Beiträge]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Kategorie:Offline in Bearbeitung|Offline in Bearbeitung]]&lt;br /&gt;
{{Hauptseite_Aufgaben}}&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;
&amp;lt;!-- Kategorien --&amp;gt;&lt;br /&gt;
&amp;lt;!-- ------------------------------- --&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td colspan=&amp;quot;4&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Kategorien&amp;lt;/h2&amp;gt;&lt;br /&gt;
Um einen erfolgreichen Start des Wikis zu gewährleisten, geht es in erster Linie darum das Wissen in folgenden Kategorien anzusammeln, bevor es dann an weiterführende Elemente wie z.B. [[Trampelpfade]] geht, weshalb '''folgende Kategorien erstmal Priorität haben sollten''' :&lt;br /&gt;
&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;25%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
[[OpenGL-Funktionsübersicht]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ähnlich den [http://developer.3dlabs.com/glmanpage_index.htm GL Man Pages] soll hier mit der Zeit eine Funktionsübersicht über alle OpenGL-Befehle entstehen. Allerdings sind hier auch glu-/wgl- und glx-Funktionen erlaubt...&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Kategorien : [[:Kategorie:GL|GL]] [[:Kategorie:GLU|GLU]] [[:Kategorie:GLX|GLX]] [[:Kategorie:WGL|WGL]]&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;25%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
[[OpenGL-Extensions]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Hier dürfen nur technische Erklärungen zur Nutzung einer Extension rein, also z.B. wie man VBOs lädt, was die Parameter bedeutet, etc...&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;25%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
[[Techniken und Algorithmen]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Hier kommen, wie der Name vermuten lässt Erklärungen zu, in der 3D-Echtzeitprogrammierung verwendeten, Techniken hin. Z.B. verschiedene Schattentechniken, Bump-Mapping, etc...&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;25%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
[[Hintergrundwissen]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
In diese Kategorie kommt alles rein was zum Verständnis im Bereich OpenGL/3D-Programmierung nützlich sein könnte. Also u.a. welche Puffer es unter OpenGL gibt, und für was die gut sind...&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;
&amp;lt;!-- Ausbau des Wikis --&amp;gt;&lt;br /&gt;
&amp;lt;!-- ------------------------------- --&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F6DFC2;&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;h2&amp;gt; Verbesserung des Wikis &amp;lt;/h2&amp;gt;&lt;br /&gt;
Wer Lust hat kann mithelfen den Wiki zu verbessern, in dem er einfach auf '''Seite bearbeiten''' klickt. Möchte man einen neuen Artikel erstellen, so sollte man sich vorher die '''[[DGL Wiki:Hinweise zum Artikel erstellen|Hinweise zum Artikel erstellen]]''' durchlesen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Diskussionen''' zum Wiki selbst (nicht zu einzelnen Artikeln) sollten zentral in unserem [http://www.delphigl.com/forum/index.php Forum] und nicht im Wiki selbst ausgetragen werden.&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;
&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F0F8FF;&amp;quot;&amp;gt;&lt;br /&gt;
Viel Spaß beim Stöbern und Mitwirken, euer DGL-Team!&lt;br /&gt;
&lt;br /&gt;
[[Bild:opengl.gif]]&amp;lt;br&amp;gt;&lt;br /&gt;
Powered by [[OpenGL]]&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;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Transparenz&amp;diff=12125</id>
		<title>Transparenz</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Transparenz&amp;diff=12125"/>
				<updated>2004-09-09T13:52:12Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Darstellung transparenter [[Primitive]] mit Hilfe von [[Blenden|Blending]]&lt;br /&gt;
* Darstellung transparenter [[Texturen]] mit Hilfe von [[Multitexturing]]&lt;br /&gt;
* Transparenz mit Hilfe von [[Alphamasking]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Multitexturing&amp;diff=2251</id>
		<title>Multitexturing</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Multitexturing&amp;diff=2251"/>
				<updated>2004-09-09T08:07:55Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was ist Multitexturing? ==&lt;br /&gt;
&lt;br /&gt;
Multitexturing bietet die Möglichkeit, wie der Name bereits vermuten lässt, auch mehrere Texturen auf ein Primitiv zu positionieren.&lt;br /&gt;
&lt;br /&gt;
== Seit wann wird Multitexturing unterstützt? ==&lt;br /&gt;
&lt;br /&gt;
Damit Multitexturing verwendet werden kann muss die Grafikkarte über mindestens 2 Textureneinheiten verfügen. Seit der Riva TNT wird Multitexturing von allen Grafikkarten unterstützt und man kann inzwischen davon ausgehen dass Multitexturing auf nahezu jedem Rechner verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
== Wo findet Multitexturing Anwendung? ==&lt;br /&gt;
&lt;br /&gt;
In heutigen Spielen ist Multitexturing ein unverzichtbares Mittel geworden. Seine häufigste Anwendung findet Multitexturing beim so genannten [[Lightmaps|Lightmapping]] und dem [[Detailmapping]].&lt;br /&gt;
&lt;br /&gt;
== Wichtige Funktionen ==&lt;br /&gt;
&lt;br /&gt;
Aufgrund der historischen Entwicklung gibt es mehrere Funktionen und Konstanten mit unterschiedlichem Namen, die jedoch dieselbe Wirkung erzielen. In heutigen Anwendungen sollte auf die ARB-Variante besser verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Bevor man in einem Programm Multitexturing verwendet, sollte man sicherheitshalber prüfen, ob dieses von der genutzten Grafikkarte überhaupt unterstützt wird. Die einfachste Möglichkeit hierfür ist abzufragen, wie viele Textureinheiten unterstützt werden. Dies kann mit Hilfe des Befehls [[glGetInteger]] und dem Token GL_MAX_TEXTURE_UNITS oder GL_MAX_TEXTURE_UNITS_ARB geschehen.&lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl [[glActiveTexture]] bzw. [[glActiveTextureARB]] kann die gewünschte Textureinheit aktiviert werden. Nach dem Aufruf dieser Funktion beziehen sich alle Befehle die auf die Textur einwirken auf die gewählte Textureneinheit.&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe der Funktion [[glTexEnv]] kann bestimmt werden, wie die Texturen kombiniert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Die Texturkoordinaten werden beim Multitexturing nicht mit dem Befehl [[glTexCoord]] sondern mit dem Befehl [[glMutliTexCoord]] bzw [[glMultiTexCoordARB]] übergeben.&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Multitexturing&amp;diff=2240</id>
		<title>Multitexturing</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Multitexturing&amp;diff=2240"/>
				<updated>2004-09-09T07:24:00Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was ist Multitexturing? ==&lt;br /&gt;
&lt;br /&gt;
Multitexturing bietet die Möglichkeit, wie der Name bereits vermuten lässt, auch mehrere Texturen auf ein Primitiv zu positionieren.&lt;br /&gt;
&lt;br /&gt;
== Seit wann wird Multitexturing unterstützt? ==&lt;br /&gt;
&lt;br /&gt;
Damit Multitexturing verwendet werden kann muss die Grafikkarte über mindestens 2 Textureneinheiten verfügen. Seit der Riva TNT wird Multitexturing von allen Grafikkarten unterstützt und man kann inzwischen davon ausgehen dass Multitexturing auf nahezu jedem Rechner verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
== Wo findet Multitexturing Anwendung? ==&lt;br /&gt;
&lt;br /&gt;
In heutigen Spielen ist Multitexturing ein unverzichtbares Mittel geworden. Seine häufigste Anwendung findet Multitexturing beim so genannten [[Lightmaps|Lightmapping]] und dem [[Detailmapping]].&lt;br /&gt;
&lt;br /&gt;
== Wichtige Funktionen ==&lt;br /&gt;
&lt;br /&gt;
Aufgrund der historischen Entwicklung gibt es mehrere Funktionen und Konstanten mit unterschiedlichem Namen, die jedoch dieselbe Wirkung erzielen. In heutigen Anwendungen sollte auf die ARB-Variante besser verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Bevor man in einem Programm Multitexturing verwendet, sollte man sicherheitshalber prüfen, ob dieses von der genutzten Grafikkarte überhaupt unterstützt wird. Die einfachste Möglichkeit hierfür ist abzufragen, wie viele Textureinheiten unterstützt werden. Dies kann mit Hilfe des Befehls [[glGetInteger]] und dem Token GL_MAX_TEXTURE_UNITS oder GL_MAX_TEXTURE_UNITS_ARB geschehen.&lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl [[glActiveTexture]] bzw. [[glActiveTextureARB]] kann die gewünschte Textureinheit aktiviert werden. Nach dem Aufruf dieser Funktion beziehen sich alle Befehle die auf die Textur einwirken auf die gewählte Textureneinheit.&lt;br /&gt;
&lt;br /&gt;
Die Texturkoordinaten werden beim Multitexturing nicht mit dem Befehl [[glTexCoord]] sondern mit dem Befehl [[glMutliTexCoord]] bzw [[glMultiTexCoordARB]] übergeben.&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Detail_Mapping&amp;diff=2703</id>
		<title>Detail Mapping</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Detail_Mapping&amp;diff=2703"/>
				<updated>2004-09-09T07:19:33Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was ist Detailmapping ==&lt;br /&gt;
&lt;br /&gt;
Beim Detailmapping wird eine Basistextur mit Hilfe von [[Multitexturing]] mit einer Detailtextur auf der sich beispielsweise Dreckflecken befinden kombiniert. Auf diese Art und Weise lassen sich Details wie Schmutzflecken oder Blutflecken leicht darstellen.&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=OpenGL-Funktions%C3%BCbersicht&amp;diff=2241</id>
		<title>OpenGL-Funktionsübersicht</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=OpenGL-Funktions%C3%BCbersicht&amp;diff=2241"/>
				<updated>2004-09-09T07:13:23Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: Vorschau gefunden&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was hier hinein gehört  ==&lt;br /&gt;
&lt;br /&gt;
Ähnlich den [http://developer.3dlabs.com/glmanpage_index.htm GL Man Pages] soll hier mit der Zeit eine Funktionsübersicht über alle OpenGL-Befehle entstehen. Allerdings sind hier auch glu-/wgl- und glx-Funktionen erlaubt. Konstanten bitte nicht hier im Inhaltsverzeichnis einfügen, genausowenig wie [[OpenGL-Extensions]].&lt;br /&gt;
Bitte achtet darauf die Funktionen zu gruppieren, also alle gl*-Befehle beieinander, und alle glu*-Befehle auch beieinander.&lt;br /&gt;
&lt;br /&gt;
Bitte haltet euch bei der Formatierung der Befehlsbeschreibung an die Vorlagen aus den GL Man Pages (ich führe hier mal glBegin als Beispiel an), und erklärt nicht mehr als nötig. &lt;br /&gt;
Wenn ihr also einen Befehl habt der etwas mit VertexArrays zu tun hat, dann gehört dort '''nicht''' hinein was ein VertexArray ist oder bringt. Das gehört dann nach [[Techniken und Algorithmen]] oder [[Hintergrundwissen]] (je nach Thematik) und sollte dann in der Funktionsbeschreibung als ''interner Link'' untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Wichtiger Hinweis ''' : Bei der Funktionsübersicht ist v.a. eine einheitliche Gliederung der Artikel wichtig. Deshalb haltet euch bitte an [[Funktionsvorlage|folgende Vorlage]]!&lt;br /&gt;
&lt;br /&gt;
==Die neuen Kategorien==&lt;br /&gt;
Seit der neuen Version des Wikis ist es möglich einen Artikel einer Kategorie zuzuordnen.&lt;br /&gt;
Man ordnet einen Artikel einer Kategorie zu, in dem man '''am Ende des Artikels einen Link zu der Kategrie erstellt''' der er zugeordnet werden soll&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|+Beispiel&lt;br /&gt;
|&lt;br /&gt;
{| border=&amp;quot;0&amp;quot; cellspacing=&amp;quot;4&amp;quot;&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[[Kategorie:GL|Name ohne &amp;quot;Gl&amp;quot;]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Das sind die neuen Kategorien:&lt;br /&gt;
*[[:Kategorie:GL]]&lt;br /&gt;
*[[:Kategorie:GLU]]&lt;br /&gt;
*[[:Kategorie:GLX]]&lt;br /&gt;
*[[:Kategorie:WGL]]&lt;br /&gt;
&lt;br /&gt;
== GL ==&lt;br /&gt;
Abkürzung für '''G'''raphics '''L'''ibrary, hierunter fallen alle Funktionen die direkter Bestandteil (entweder als Kernfunktion oder über Extensions) der OpenGL sind.&lt;br /&gt;
&lt;br /&gt;
=== A ===&lt;br /&gt;
[[glAccum]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glActiveTexture]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glActiveTextureARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glAddSwapHintRectWIN]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glAlphaFunc]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glAreTexturesResident]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glArrayElement]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glAttachObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== B ===&lt;br /&gt;
[[glBegin]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glBindAttribLocationARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glBitmap]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glBlendFunc]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== C ===&lt;br /&gt;
[[glCallList]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCallLists]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClear]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearAccum]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearColor]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearDepth]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearIndex]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearStencil]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClipPlane]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glColor]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glColorMask]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glColorMaterial]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glColorPointer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCompileShaderARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCopyPixels]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCreateProgramObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCreateShaderObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCullFace]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== D ===&lt;br /&gt;
[[glDeleteLists]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDeleteObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDetachObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDepthFunc]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDepthMask]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDepthRange]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDisable]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[GlDisableClientState]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDisableVertexAttribArrayARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDrawArrays]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDrawBuffer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDrawPixels]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== E ===&lt;br /&gt;
[[glEdgeFlag]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEdgeFlagPointer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEnable]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEnableClientState]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEnableVertexAttribArrayARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEnd]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEndList]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEvalCoord]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEvalMesh]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEvalPoint]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== F ===&lt;br /&gt;
[[glFeedbackBuffer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFinish]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFlush]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFog]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFrontFace]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFrustum]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== G ===&lt;br /&gt;
[[glGenLists]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGet]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetActiveAttribARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetActiveUniformARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetAttachedObjectsARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetAttribLocationARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetBoolean]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetClipPlane]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetDoublev]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetError]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetFloatv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetHandleARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetInfoLogARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetIntegerv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetLight]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetMap]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetMaterial]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetObjectParameterARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetPixelMap]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetPointerv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetPolygonStipple]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetShaderSourceARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetString]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexEnv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexGen]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexImage]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexLevelParameter]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexParameter]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetUniformARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetUnifromLocationARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetVertexAttribARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetVertexAttribPointervARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== H ===&lt;br /&gt;
[[glHint]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== I ===&lt;br /&gt;
[[glIndex]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glIndexMask]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glIndexPointer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glInitNames]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glIsEnabled]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glIsList]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== L ===&lt;br /&gt;
[[glLight]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLightModel]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLineStipple]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLineWidth]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLinkProgramARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glListBase]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLoadIdentity]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLoadMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLoadName]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLogicOp]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== M ===&lt;br /&gt;
[[glMap1]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMap2]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMapGrid]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMaterial]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMatrixMode]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMutliTexCoord]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMutliTexCoordARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMultMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== N ===&lt;br /&gt;
[[glNewList]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glNormal]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 0 ===&lt;br /&gt;
[[glOrtho]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== P ===&lt;br /&gt;
[[glPassThrough]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPixelMap]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPixelStore]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPixelTransfer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPixelZoom]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPointSize]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPolygonMode]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPolygonStipple]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPopAttrib]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPopMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPopName]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPushAttrib]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPushMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPushName]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== R ===&lt;br /&gt;
[[glRasterPos]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glReadBuffer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glReadPixels]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glRect]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glRenderMode]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glRotate]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== S ===&lt;br /&gt;
[[glScale]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glScissor]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glSelectBuffer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glShadeModel]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glShaderSourceARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glStencilFunc]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glStencilMask]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glStencilOp]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== T ===&lt;br /&gt;
[[glTexCoord]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTexEnv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTexGen]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTexImage]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTexParameter]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTranslate]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== U ===&lt;br /&gt;
[[glUniformARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glUseProgramObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== V ===&lt;br /&gt;
[[glValidateProgramARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glVertex]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glVertexAttribARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glVertexAttribPointerARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glVertexPointer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glViewport]]&lt;br /&gt;
&lt;br /&gt;
== GLU ==&lt;br /&gt;
(Was ist die [[GLU]]?)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== B ===&lt;br /&gt;
[[gluBeginCurve]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBeginPolygon]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBeginSurface]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBeginTrim]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBuild1DMipmaps]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBuild2DMipmaps]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== C ===&lt;br /&gt;
[[gluCylinder]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== D ===&lt;br /&gt;
[[gluDeleteNurbsRenderer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluDeleteQuadric]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluDeleteTess]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluDisk]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== E ===&lt;br /&gt;
[[gluEndCurve]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluEndPolygon]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluEndSurface]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluEndTrim]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluErrorString]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== G ===&lt;br /&gt;
[[gluGetNurbsProperty]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluGetString]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluGetTessProperty]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== L ===&lt;br /&gt;
[[gluLoadSamplingMatrices]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluLookAt]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== N ===&lt;br /&gt;
[[gluNewNurbsRenderer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNewQuadric]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNewTess]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNextContour]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNurbsCallback]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNurbsCurve]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNurbsProperty]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNurbsSurface]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== O ===&lt;br /&gt;
[[gluOrtho2D]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== P ===&lt;br /&gt;
[[gluPartialDisk]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluPerspective]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluPickMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluProject]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluPwlCurve]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Q ===&lt;br /&gt;
[[gluQuadricCallback]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluQuadricDrawStyle]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluQuadricNormals]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluQuadricOrientation]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluQuadricTexture]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== S ===&lt;br /&gt;
[[gluScaleImage]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluSphere]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== T ===&lt;br /&gt;
[[gluTessBeginContour]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessBeginPolygon]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessCallback]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessEndContour]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessEndPolygon]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessNormal]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessProperty]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessVertex]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== U ===&lt;br /&gt;
[[gluUnProject]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== GLX ==&lt;br /&gt;
(Was ist die [[GLX]]?)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[glxChooseVisual]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glxCreateContext]]&amp;lt;br&amp;gt; &lt;br /&gt;
[[glxDestroyContext]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glxMakeCurrent]]&amp;lt;br&amp;gt;  &lt;br /&gt;
[[glxSwapBuffers]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== WGL ==&lt;br /&gt;
(Was ist die [[WGL]]?)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== C ===&lt;br /&gt;
[[wglCreateContext]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglCreatePbufferARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== D ===&lt;br /&gt;
[[wglDeleteContext]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglDestroyPbufferARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== G ===&lt;br /&gt;
[[wglGetCurrentContext]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglGetCurrentDC]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglGetCurrentReadDC]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglGetPbufferDCARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglGetProcAddress]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== M ===&lt;br /&gt;
[[wglMakeCurrent]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Q ===&lt;br /&gt;
[[wglQueryPbufferARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== R ===&lt;br /&gt;
[[wglReleasePbufferDCARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== S ===&lt;br /&gt;
[[wglShareLists]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglSwapIntervalEXT]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== U ===&lt;br /&gt;
[[wglUseFontBitmaps]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglUseFontOutlines]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Externe Funktionen ==&lt;br /&gt;
Hier sind alle Funktionen zu finden, die zwar direkt nichts mit OpenGL zu tun haben, aber trotzdem im Normalfall zur Nutzung der GL benötigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Win32 Funktionen ===&lt;br /&gt;
[[ChoosePixelFormat]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[DescribePixelFormat]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[GetPixelFormat]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[SetPixelFormat]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[SwapBuffers]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Linux / Unix Funktionen ===&lt;br /&gt;
[[XCloseDisplay]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[XDefaultScreen]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[XOpenDisplay]]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=OpenGL-Funktions%C3%BCbersicht&amp;diff=2238</id>
		<title>OpenGL-Funktionsübersicht</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=OpenGL-Funktions%C3%BCbersicht&amp;diff=2238"/>
				<updated>2004-09-09T07:12:09Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was hier hinein gehört  ==&lt;br /&gt;
&lt;br /&gt;
Ähnlich den [http://developer.3dlabs.com/glmanpage_index.htm GL Man Pages] soll hier mit der Zeit eine Funktionsübersicht über alle OpenGL-Befehle entstehen. Allerdings sind hier auch glu-/wgl- und glx-Funktionen erlaubt. Konstanten bitte nicht hier im Inhaltsverzeichnis einfügen, genausowenig wie [[OpenGL-Extensions]].&lt;br /&gt;
Bitte achtet darauf die Funktionen zu gruppieren, also alle gl*-Befehle beieinander, und alle glu*-Befehle auch beieinander.&lt;br /&gt;
&lt;br /&gt;
Bitte haltet euch bei der Formatierung der Befehlsbeschreibung an die Vorlagen aus den GL Man Pages (ich führe hier mal glBegin als Beispiel an), und erklärt nicht mehr als nötig. &lt;br /&gt;
Wenn ihr also einen Befehl habt der etwas mit VertexArrays zu tun hat, dann gehört dort '''nicht''' hinein was ein VertexArray ist oder bringt. Das gehört dann nach [[Techniken und Algorithmen]] oder [[Hintergrundwissen]] (je nach Thematik) und sollte dann in der Funktionsbeschreibung als ''interner Link'' untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Wichtiger Hinweis ''' : Bei der Funktionsübersicht ist v.a. eine einheitliche Gliederung der Artikel wichtig. Deshalb haltet euch bitte an [[Funktionsvorlage|folgende Vorlage]]!&lt;br /&gt;
&lt;br /&gt;
==Die neuen Kategorien==&lt;br /&gt;
Seit der neuen Version des Wikis ist es möglich einen Artikel einer Kategorie zuzuordnen.&lt;br /&gt;
Man ordnet einen Artikel einer Kategorie zu, in dem man '''am Ende des Artikels einen Link zu der Kategrie erstellt''' der er zugeordnet werden soll&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|+Beispiel&lt;br /&gt;
|&lt;br /&gt;
{| border=&amp;quot;0&amp;quot; cellspacing=&amp;quot;4&amp;quot;&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;[[Kategorie:GL|Name ohne &amp;quot;Gl&amp;quot;]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Das sind die neuen Kategorien:&lt;br /&gt;
*[[:Kategorie:GL]]&lt;br /&gt;
*[[:Kategorie:GLU]]&lt;br /&gt;
*[[:Kategorie:GLX]]&lt;br /&gt;
*[[:Kategorie:WGL]]&lt;br /&gt;
&lt;br /&gt;
== GL ==&lt;br /&gt;
Abkürzung für '''G'''raphics '''L'''ibrary, hierunter fallen alle Funktionen die direkter Bestandteil (entweder als Kernfunktion oder über Extensions) der OpenGL sind.&lt;br /&gt;
&lt;br /&gt;
=== A ===&lt;br /&gt;
[[glAccum]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glActiveTexture]]&lt;br /&gt;
[[glActiveTextureARB]]&lt;br /&gt;
[[glAddSwapHintRectWIN]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glAlphaFunc]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glAreTexturesResident]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glArrayElement]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glAttachObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== B ===&lt;br /&gt;
[[glBegin]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glBindAttribLocationARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glBitmap]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glBlendFunc]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== C ===&lt;br /&gt;
[[glCallList]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCallLists]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClear]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearAccum]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearColor]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearDepth]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearIndex]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClearStencil]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glClipPlane]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glColor]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glColorMask]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glColorMaterial]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glColorPointer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCompileShaderARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCopyPixels]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCreateProgramObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCreateShaderObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glCullFace]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== D ===&lt;br /&gt;
[[glDeleteLists]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDeleteObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDetachObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDepthFunc]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDepthMask]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDepthRange]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDisable]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[GlDisableClientState]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDisableVertexAttribArrayARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDrawArrays]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDrawBuffer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glDrawPixels]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== E ===&lt;br /&gt;
[[glEdgeFlag]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEdgeFlagPointer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEnable]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEnableClientState]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEnableVertexAttribArrayARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEnd]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEndList]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEvalCoord]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEvalMesh]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glEvalPoint]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== F ===&lt;br /&gt;
[[glFeedbackBuffer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFinish]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFlush]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFog]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFrontFace]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glFrustum]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== G ===&lt;br /&gt;
[[glGenLists]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGet]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetActiveAttribARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetActiveUniformARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetAttachedObjectsARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetAttribLocationARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetBoolean]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetClipPlane]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetDoublev]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetError]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetFloatv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetHandleARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetInfoLogARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetIntegerv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetLight]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetMap]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetMaterial]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetObjectParameterARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetPixelMap]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetPointerv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetPolygonStipple]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetShaderSourceARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetString]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexEnv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexGen]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexImage]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexLevelParameter]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetTexParameter]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetUniformARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetUnifromLocationARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetVertexAttribARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glGetVertexAttribPointervARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== H ===&lt;br /&gt;
[[glHint]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== I ===&lt;br /&gt;
[[glIndex]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glIndexMask]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glIndexPointer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glInitNames]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glIsEnabled]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glIsList]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== L ===&lt;br /&gt;
[[glLight]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLightModel]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLineStipple]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLineWidth]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLinkProgramARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glListBase]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLoadIdentity]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLoadMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLoadName]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glLogicOp]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== M ===&lt;br /&gt;
[[glMap1]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMap2]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMapGrid]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMaterial]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMatrixMode]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glMutliTexCoord]]&lt;br /&gt;
[[glMutliTexCoordARB]]&lt;br /&gt;
[[glMultMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== N ===&lt;br /&gt;
[[glNewList]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glNormal]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 0 ===&lt;br /&gt;
[[glOrtho]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== P ===&lt;br /&gt;
[[glPassThrough]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPixelMap]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPixelStore]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPixelTransfer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPixelZoom]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPointSize]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPolygonMode]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPolygonStipple]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPopAttrib]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPopMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPopName]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPushAttrib]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPushMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glPushName]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== R ===&lt;br /&gt;
[[glRasterPos]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glReadBuffer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glReadPixels]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glRect]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glRenderMode]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glRotate]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== S ===&lt;br /&gt;
[[glScale]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glScissor]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glSelectBuffer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glShadeModel]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glShaderSourceARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glStencilFunc]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glStencilMask]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glStencilOp]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== T ===&lt;br /&gt;
[[glTexCoord]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTexEnv]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTexGen]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTexImage]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTexParameter]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glTranslate]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== U ===&lt;br /&gt;
[[glUniformARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glUseProgramObjectARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== V ===&lt;br /&gt;
[[glValidateProgramARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glVertex]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glVertexAttribARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glVertexAttribPointerARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glVertexPointer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glViewport]]&lt;br /&gt;
&lt;br /&gt;
== GLU ==&lt;br /&gt;
(Was ist die [[GLU]]?)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== B ===&lt;br /&gt;
[[gluBeginCurve]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBeginPolygon]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBeginSurface]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBeginTrim]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBuild1DMipmaps]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluBuild2DMipmaps]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== C ===&lt;br /&gt;
[[gluCylinder]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== D ===&lt;br /&gt;
[[gluDeleteNurbsRenderer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluDeleteQuadric]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluDeleteTess]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluDisk]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== E ===&lt;br /&gt;
[[gluEndCurve]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluEndPolygon]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluEndSurface]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluEndTrim]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluErrorString]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== G ===&lt;br /&gt;
[[gluGetNurbsProperty]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluGetString]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluGetTessProperty]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== L ===&lt;br /&gt;
[[gluLoadSamplingMatrices]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluLookAt]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== N ===&lt;br /&gt;
[[gluNewNurbsRenderer]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNewQuadric]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNewTess]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNextContour]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNurbsCallback]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNurbsCurve]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNurbsProperty]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluNurbsSurface]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== O ===&lt;br /&gt;
[[gluOrtho2D]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== P ===&lt;br /&gt;
[[gluPartialDisk]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluPerspective]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluPickMatrix]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluProject]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluPwlCurve]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Q ===&lt;br /&gt;
[[gluQuadricCallback]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluQuadricDrawStyle]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluQuadricNormals]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluQuadricOrientation]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluQuadricTexture]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== S ===&lt;br /&gt;
[[gluScaleImage]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluSphere]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== T ===&lt;br /&gt;
[[gluTessBeginContour]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessBeginPolygon]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessCallback]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessEndContour]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessEndPolygon]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessNormal]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessProperty]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[gluTessVertex]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== U ===&lt;br /&gt;
[[gluUnProject]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== GLX ==&lt;br /&gt;
(Was ist die [[GLX]]?)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[glxChooseVisual]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glxCreateContext]]&amp;lt;br&amp;gt; &lt;br /&gt;
[[glxDestroyContext]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[glxMakeCurrent]]&amp;lt;br&amp;gt;  &lt;br /&gt;
[[glxSwapBuffers]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== WGL ==&lt;br /&gt;
(Was ist die [[WGL]]?)&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== C ===&lt;br /&gt;
[[wglCreateContext]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglCreatePbufferARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== D ===&lt;br /&gt;
[[wglDeleteContext]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglDestroyPbufferARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== G ===&lt;br /&gt;
[[wglGetCurrentContext]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglGetCurrentDC]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglGetCurrentReadDC]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglGetPbufferDCARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglGetProcAddress]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== M ===&lt;br /&gt;
[[wglMakeCurrent]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Q ===&lt;br /&gt;
[[wglQueryPbufferARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== R ===&lt;br /&gt;
[[wglReleasePbufferDCARB]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== S ===&lt;br /&gt;
[[wglShareLists]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglSwapIntervalEXT]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== U ===&lt;br /&gt;
[[wglUseFontBitmaps]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[wglUseFontOutlines]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Externe Funktionen ==&lt;br /&gt;
Hier sind alle Funktionen zu finden, die zwar direkt nichts mit OpenGL zu tun haben, aber trotzdem im Normalfall zur Nutzung der GL benötigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Win32 Funktionen ===&lt;br /&gt;
[[ChoosePixelFormat]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[DescribePixelFormat]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[GetPixelFormat]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[SetPixelFormat]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[SwapBuffers]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Linux / Unix Funktionen ===&lt;br /&gt;
[[XCloseDisplay]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[XDefaultScreen]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[XOpenDisplay]]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Multitexturing&amp;diff=2239</id>
		<title>Multitexturing</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Multitexturing&amp;diff=2239"/>
				<updated>2004-09-09T07:06:18Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was ist Multitexturing? ==&lt;br /&gt;
&lt;br /&gt;
Multitexturing bietet die Möglichkeit, wie der Name bereits vermuten lässt, auch mehrere Texturen auf ein Primitiv zu positionieren.&lt;br /&gt;
&lt;br /&gt;
== Seit wann wird Multitexturing unterstützt? ==&lt;br /&gt;
&lt;br /&gt;
Damit Multitexturing verwendet werden kann muss die Grafikkarte über mindestens 2 Textureneinheiten verfügen. Seit der Riva TNT wird Multitexturing von allen Grafikkarten unterstützt und man kann inzwischen davon ausgehen dass Multitexturing auf nahezu jedem Rechner verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
== Wo findet Multitexturing Anwendung? ==&lt;br /&gt;
&lt;br /&gt;
In heutigen Spielen ist Multitexturing ein unverzichtbares Mittel geworden. Seine häufigste Anwendung findet Multitexturing beim so genannten [[Lightmapping]] und dem [[Detailmapping]]. &lt;br /&gt;
&lt;br /&gt;
== Wichtige Funktionen ==&lt;br /&gt;
&lt;br /&gt;
Aufgrund der historischen Entwicklung gibt es mehrere Funktionen und Konstanten mit unterschiedlichem Namen, die jedoch dieselbe Wirkung erzielen. In heutigen Anwendungen sollte auf die ARB-Variante besser verzichtet werden.&lt;br /&gt;
&lt;br /&gt;
Bevor man in einem Programm Multitexturing verwendet, sollte man sicherheitshalber prüfen, ob dieses von der genutzten Grafikkarte überhaupt unterstützt wird. Die einfachste Möglichkeit hierfür ist abzufragen, wie viele Textureinheiten unterstützt werden. Dies kann mit Hilfe des Befehls [[glGetInteger]] und dem Token GL_MAX_TEXTURE_UNITS oder GL_MAX_TEXTURE_UNITS_ARB geschehen.&lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl [[glActiveTexture]] bzw. [[glActiveTextureARB]] kann die gewünschte Textureinheit aktiviert werden. Nach dem Aufruf dieser Funktion beziehen sich alle Befehle die auf die Textur einwirken auf die gewählte Textureneinheit.&lt;br /&gt;
&lt;br /&gt;
Die Texturkoordinaten werden beim Multitexturing nicht mit dem Befehl [[glTexCoord]] sondern mit dem Befehl [[glMutliTexCoord]] bzw [[glMultiTexCoordARB]] übergeben.&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Hauptseite&amp;diff=2243</id>
		<title>Hauptseite</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Hauptseite&amp;diff=2243"/>
				<updated>2004-09-09T06:30:29Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F0F8FF;&amp;quot;&amp;gt;&lt;br /&gt;
'''Infos'''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Die [http://www.delphigl.com Delphi-OpenGL-Community] hat es sich mit diesem Wiki zum Ziel gemacht eine freie Wissensdatenbank rund um das Thema [[OpenGL]] zu erschaffen, an der alle Interessierten mitwirken, oder einfach nur Wissen nachschlagen können.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
'''News'''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Die aktuelle installierte Version des Wiki ist 1.3.2. Uns sind keine Probleme bekannt.&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;180px&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F0F8FF;&amp;quot;&amp;gt;&lt;br /&gt;
'''Aktuelles'''&amp;lt;br&amp;gt;&lt;br /&gt;
[[Spezial:Statistics|{{NUMBEROFARTICLES}}]] [[Spezial:Newpages|Artikel]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Spezial:Wantedpages|Gewünschte Artikel]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[Unvollständige Beiträge]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[:Kategorie:Offline in Bearbeitung|Offline in Bearbeitung]]&amp;lt;br&amp;gt;&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;
&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F6DFC2;&amp;quot;&amp;gt;&lt;br /&gt;
'''Bitte lesen'''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Wer '''aktiv mitwirken''' will, sollte sich auf jeden Fall '''an die in jeder Kategorie ausgewiesene Thematik halten''' und sich (falls noch keine Wiki-Erfahrungen vorhanden sind) die [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide Bedienungsanleitung] des MediaWikis  oder die [[DGL_Wiki:Editierhilfe|Editierhilfe]] unseres Wikis durchlesen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Hinweis für Wiki-Bilder: '''Wenn ihr Bilder (nur wenn diese von euch stammen!) hochladen wollt, dann verpasst diesen bitte unser DGL-Wiki-[[Wasserzeichen]].&lt;br /&gt;
&lt;br /&gt;
Wer seiner Meinung nach '''zu wenig Zeit''' hat einen '''kompletten Artikel''' zu erstellen kann [[Unvollständige Beiträge | hier]] an einem '''unvollständigen Artikel weiterarbeiten''' bzw. Ergänzungen machen.&lt;br /&gt;
&lt;br /&gt;
'''Diskussionen''' zum Wiki selbst (nicht zu einzelnen Artikeln) sollten zentral in unserem [http://www.delphigl.com/forum/index.php Forum] und nicht im Wiki selbst ausgetragen werden.&lt;br /&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 style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
'''Kategorien'''&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Um einen erfolgreichen Start des Wikis zu gewährleisten, geht es in erster Linie darum das Wissen in folgenden Kategorien anzusammeln, bevor es dann an weiterführende Elemente wie z.B. [[Trampelpfade]] geht, weshalb '''folgende Kategorien erstmal Priorität haben sollten''' :&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;
&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;25%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
[[OpenGL-Funktionsübersicht]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Ähnlich den [http://developer.3dlabs.com/glmanpage_index.htm GL Man Pages] soll hier mit der Zeit eine Funktionsübersicht über alle OpenGL-Befehle entstehen. Allerdings sind hier auch glu-/wgl- und glx-Funktionen erlaubt...&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;25%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
[[OpenGL-Extensions]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Hier dürfen nur technische Erklärungen zur Nutzung einer Extension rein, also z.B. wie man VBOs lädt, was die Parameter bedeutet, etc...&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;25%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
[[Techniken und Algorithmen]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Hier kommen, wie der Name vermuten lässt Erklärungen zu, in der 3D-Echtzeitprogrammierung verwendeten, Techniken hin. Z.B. verschiedene Schattentechniken, Bump-Mapping, etc...&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td width=&amp;quot;25%&amp;quot; style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#D9EFDE;&amp;quot;&amp;gt;&lt;br /&gt;
[[Hintergrundwissen]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
In diese Kategorie kommt alles rein was zum Verständnis im Bereich OpenGL/3D-Programmierung nützlich sein könnte. Also u.a. welche Puffer es unter OpenGL gibt, und für was die gut sind...&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;
&amp;lt;table border=&amp;quot;0&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;tr&amp;gt;&lt;br /&gt;
  &amp;lt;td style=&amp;quot;margin: 0; margin-right:10px; border: 1px solid #dfdfdf; padding: 0 1em 1em 1em; background-color:#F0F8FF;&amp;quot;&amp;gt;&lt;br /&gt;
Viel Spaß beim Stöbern und Mitwirken, euer DGL-Team!&lt;br /&gt;
&lt;br /&gt;
[[Bild:opengl.jpg]]&amp;lt;br&amp;gt;&lt;br /&gt;
Powered by [[OpenGL]]&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;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=glBlendFunc&amp;diff=2624</id>
		<title>glBlendFunc</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=glBlendFunc&amp;diff=2624"/>
				<updated>2004-09-08T12:09:21Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: /* glBlendFunc */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= glBlendFunc =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Name ==&lt;br /&gt;
'''glBlendFunc''' - Setzt bestimmte Pixel-Berechnungen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Delphi-Spezifikation ==&lt;br /&gt;
 procedure '''glBlendFunc'''(''sfactor'' : TGLEnum; ''dfactor'': TGLEnum);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;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;'''sfactor'''&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;Gibt an, wie der Rot-, Grün-, Blau- und Alphaanteil des Quell-Blendfaktors berechned wird. Folgende symbolische Konstanten sind erlaubt : '''GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR_EXT, GL_ONE_MINUS_CONSTANT_COLOR_EXT, GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT und GL_SRC_ALPHA_SATURATE'''. Vorgabewert ist '''GL_ONE'''.&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&amp;gt;'''dfactor'''&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;Gibt an, wie der Rot-, Grün-, Blau- und Alphaanteil des Quell-Blendfaktors berechned wird. Folgende symbolische Konstanten sind erlaubt : '''GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR_EXT, GL_ONE_MINUS_CONSTANT_COLOR_EXT, GL_CONSTANT_ALPHA_EXT und GL_ONE_MINUS_CONSTANT_ALPHA_EXT'''. Vorgabewert ist '''GL_ZERO'''.&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;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
Im RGBA-Modus, können Pixel so gezeichnet werden, dass anhand einer Funktion die ankommenden RGBA-Werte (Quelle) mit dem bereits im Framepuffer befindlichen RGBA-Werten (Ziel) gemischt werden. Mischung ist als Vorgabe deaktiviert, kann jedoch mit [[glEnable]]/[[glEnable|glDisable]] und dem Token '''GL_BLEND''' gesteuert werden.&lt;br /&gt;
&lt;br /&gt;
'''glBlendFunc''' beschreibt die Funktion der Mischung, sofern aktiviert. ''sfactor'' gibt dabei an welche Methode genutzt wird um die Quellfarbkomponenten zu skalieren. ''dfactor'' gibt an, welche der Methode genutzt wird um die Zielfarbkomponenten zu skalieren. Die möglichen Methoden werden in der folgenden Tabelle beschrieben, wobei jede insgesamt vier Skalierungsfaktoren besitzt, für die vier Komponenten einer RGBA-Farbe.&lt;br /&gt;
&lt;br /&gt;
In der Tabelle (und allen folgenden Gleichungen), werden Quell- bzw. Zielfarbkomponenten als (Rs, Gs, Bs, As) und (Rd, Gd, Bd, Ad) dargestellt. Diese Komponenten besitzen Ganzzahlwerte, die zwischen 0 und (kR, kG, kB, kA) liegen, wobei &lt;br /&gt;
&lt;br /&gt;
 kc = 2^mc - 1;&lt;br /&gt;
&lt;br /&gt;
und (mR, mG, mB, mA) gleich der Zahl der Rot-, Grün-, Blau- und Alphabitflächen ist.&lt;br /&gt;
&lt;br /&gt;
Konstante Farbkomponenten werden als (Rc, Gc, Bc, Ac) angegeben und werden nicht mit (kR, kG, kB, kA) skaliert, da sie bereits im Intervall [0,1] liegen.&lt;br /&gt;
&lt;br /&gt;
Quell- und Zielskalierungsfaktoren werden als (sR, sG, sB, sA) und (dR, dG, dB, dA) angegeben. Die in der Tabelle beschriebenen Skalierungsfaktoren, angegeben als (fR, fG, fB, fA) repräsentieren entweder Quell- oder Zielfaktoren. Alle Skalierungsfaktoren liegen im Intervall [0,1].&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
|'''Parameter'''&lt;br /&gt;
|'''(fR, fG, fB, fA)'''&lt;br /&gt;
|-&lt;br /&gt;
|GL_ZERO	&lt;br /&gt;
|(0,0,0,0)&lt;br /&gt;
|-&lt;br /&gt;
|GL_ONE	&lt;br /&gt;
|(1,1,1,1)&lt;br /&gt;
|-&lt;br /&gt;
|GL_SRC_COLOR	&lt;br /&gt;
|(Rs/kR, Gs/kG, Bs/kB, As/kA)&lt;br /&gt;
|-&lt;br /&gt;
|GL_ONE_MINUS_SRC_COLOR	&lt;br /&gt;
|(1,1,1,1) - (Rs/kR, Gs/kG, Bs/kB, As/kA)&lt;br /&gt;
|-&lt;br /&gt;
|GL_DST_COLOR	&lt;br /&gt;
|(Rd/kR, Gd/kG, Bd/kB, Ad/kA)&lt;br /&gt;
|-&lt;br /&gt;
|GL_ONE_MINUS_DST_COLOR	&lt;br /&gt;
|(1,1,1,1) - (Rd/kR, Gd/kG, Bd/kB, Ad/kA)&lt;br /&gt;
|-&lt;br /&gt;
|GL_SRC_ALPHA	&lt;br /&gt;
|(As/kA, As/kA, As/kA, As/kA)&lt;br /&gt;
|-&lt;br /&gt;
|GL_ONE_MINUS_SRC_ALPHA	&lt;br /&gt;
|(1,1,1,1) - (As/kA, As/kA, As/kA, As/kA)&lt;br /&gt;
|-&lt;br /&gt;
|GL_DST_ALPHA	&lt;br /&gt;
|(Ad/kA, Ad/kA, Ad/kA, Ad/kA)&lt;br /&gt;
|-&lt;br /&gt;
|GL_ONE_MINUS_DST_ALPHA	&lt;br /&gt;
|(1,1,1,1) - (Ad/kA, Ad/kA, Ad/kA, Ad/kA)&lt;br /&gt;
|-&lt;br /&gt;
|GL_SRC_ALPHA_SATURATE	&lt;br /&gt;
|(i,i,i,1)&lt;br /&gt;
|-&lt;br /&gt;
|GL_CONSTANT_COLOR_EXT	&lt;br /&gt;
|(Rc, Gc, Bc, Ac)&lt;br /&gt;
|-&lt;br /&gt;
|GL_ONE_MINUS_CONSTANT_COLOR_EXT	&lt;br /&gt;
|(1,1,1,1) - (Rc, Gc, Bc, Ac)&lt;br /&gt;
|-&lt;br /&gt;
|GL_CONSTANT_ALPHA_EXT	&lt;br /&gt;
|(Ac, Ac, Ac, Ac)&lt;br /&gt;
|-&lt;br /&gt;
|GL_ONE_MINUS_CONSTANT_ALPHA_EXT	&lt;br /&gt;
|(1,1,1,1) - (Ac, Ac, Ac, Ac)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In der Tabelle ist&lt;br /&gt;
 &lt;br /&gt;
 i = min(As, kA - Ad) /kA&lt;br /&gt;
&lt;br /&gt;
Um die gemischten RGBA-Werte eines Pixels im RGBA-Modus zu ermitteln, nutzt das System folgende Gleichungen (wenn die Mischungs-Gleichung Erweiterung nicht unterstützt wird) :&lt;br /&gt;
&lt;br /&gt;
 Rd = min(kR, RssR + RddR)&lt;br /&gt;
 Gd = min(kG, GssG + GddR)&lt;br /&gt;
 Bd = min(kB, BssB + BddB)&lt;br /&gt;
 Ad = min(kA, AssB + AddA)&lt;br /&gt;
&lt;br /&gt;
Trotz der offensichtlichen Präzisions obiger Gleichungen, ist die Mischungsarithmetik nicht exakt spezifiziert, aufgrund Mischungsoperationen mit unpräzisen Ganzzahlwerten. Bei einem Mischungsfaktor von 1 ist jedoch garantiert, dass dieser seinen Mulitplikanten nicht verändert, und ein Mischungsfaktor gleich 0 verrringert seinen Multiplikanten auf 0. Wenn ''sfactor'' z.B. '''GL_SCR_ALPHA''' ist, und ''dfactor'' gleich '''GL_ONE_MINUS_SRC_ALPHA''', dann ist ''As'' gleich ''kA'', und die Funktionen können auf ihre einfache Entsprechung reduziert werden :&lt;br /&gt;
&lt;br /&gt;
 Rd = Rs&lt;br /&gt;
 Gd = Gs&lt;br /&gt;
 Bd = Bs&lt;br /&gt;
 Ad = As&lt;br /&gt;
&lt;br /&gt;
Wenn die Erweiterung für Mischungsgleichungen vorhanden ist, werden die gemischten RGBA-Werte anhand der gesetzten Mischungsgleichung gesetzt. Siehe dazu [[glBlendEquation]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
'''Transparenz''' implementiert man am besten mit den Mischungsfunktionen ('''GL_SRC_ALPHA''', '''GL_ONE_MINUS_SRC_ALPHA) und Sortierung der Primitiven von hinten nach vorne. &lt;br /&gt;
&lt;br /&gt;
Die Mischungsfunktion('''GL_SRC_ALPHA''', '''GL_ONE_MINUS_SRC_ALPHA''') ist auch zum '''Rendern kantengeglätteter''' Punkte nützlich, egal in welcher Reihenfolge diese vorkommen.&lt;br /&gt;
&lt;br /&gt;
'''Kantenglättung von Polygonen''' lässt sich mit der Mischungsfunktion ('''GL_SRC_ALPHA_SATURATE''', '''GL_ONE''') optimieren, wobei die Polygone von vorne nach hinten sortiert werden. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
Der Alpha-Eingangswert (Quelle) kann im Endeffekt als Materialdurchlässigkeit betrachtet werden, reichend von ''KA'' = 1, also komplett solide, bis ''KA''=0, was ein komplett transparentes (=unsichtbares) Material darstellen würde.&lt;br /&gt;
&lt;br /&gt;
Wenn mehr als ein Farbpuffer zum Rendern aktiv ist, wird die GL für jeden dieser Puffer separat Mischung durchführen, unter Nutzung des entsprechenden Pufferinhaltes als Zielkomponente. Siehe [[glDrawBuffer]].&lt;br /&gt;
&lt;br /&gt;
Mischung funktioniert übrigens nur im RGBA-Modus. Im Farbindex-Modus nicht. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Fehlermeldungen ==&lt;br /&gt;
'''GL_INVALID_ENUM''' wird generiert, wenn ''sfactor'' oder ''dfactor'' keine gültigen Werte darstellen.&lt;br /&gt;
&lt;br /&gt;
'''GL_INVALID_OPERATION''' wird generiert, wenn '''glBlendFunc''' in einem [[glBegin]]-[[glEnd]] Block aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Zugehörige Wertrückgaben ==&lt;br /&gt;
'''glGet''' mit dem Argument '''GL_BLEND_SRC'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''glGet''' mit dem Argument '''GL_BLEND_DST'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''glGet''' mit dem Argument '''GL_BLEND_COLOR_EXT'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''glIsEnabled''' mit dem Argument '''GL_BLEND'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[glAlphaFunc]], [[glClear]], [[glBlendEquation]], [[glBlendFuncSeparate]], [[glDrawBuffer]], [[glEnable]], [[glLogicOp]], [[glStencilFunc]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Literatur ==&lt;br /&gt;
[[RedBook]] Kapitel 7&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:GL|BlendFunc]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Farbpuffer&amp;diff=2301</id>
		<title>Farbpuffer</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Farbpuffer&amp;diff=2301"/>
				<updated>2004-08-28T20:05:37Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was ist der Colorbuffer? ==&lt;br /&gt;
&lt;br /&gt;
Der Colorbuffer enthält die Farbinformationen der [[Fragment|Fragmente]] im [[Framebuffer]].&lt;br /&gt;
&lt;br /&gt;
== Wichtige Funktionen ==&lt;br /&gt;
&lt;br /&gt;
Wie auch die anderen Buffer kann der Colorbuffer über die Funktion [[glClear]] und dem Parameter GL_COLOR_BUFFER_BIT mit einem Wert gefüllt werden.&lt;br /&gt;
Dieser Farbwert wird mit Hilfe der Funktion [[glClearColor]] definiert.&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Skybox&amp;diff=308</id>
		<title>Skybox</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Skybox&amp;diff=308"/>
				<updated>2004-07-22T21:46:17Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Wort Sky kommt aus dem Englischen und bedeutet Himmel. Skyboxen werden verwendet, um die Umgebung in 3D-Szenen darzustellen. Dazu zählen z.B. Landschaften im Hintergrund sowie Sonne, Himmel und Wolken. Da diese Orte nur als Kulisse dienen und für den Programmablauf meist ohne Bedeutung sind, verwendet man für deren Darstellung einfache [[Texturen]].&amp;lt;br&amp;gt;&lt;br /&gt;
Sobald man sich in einer Szene jedoch frei bewegen kann, entstehen mehrere Probleme. Zum einen müssen die Texturen so an einander gefügt werden, dass man den Trick nicht durchschaut und erkennt, dass es sich lediglich um Texturen handelt, zum anderen muss sich die Textur stets in gleicher Entfernung vom Beobachter befinden, damit man sich ihr nicht nähern kann. Obendrein darf die Textur jedoch andere Szenenteile, die erreichbar sind, nicht verdecken.&amp;lt;br&amp;gt;&lt;br /&gt;
Im Prinzip ist das Problem recht leicht zu lösen. Für die Darstellung der Umgebung nutzt man einen einfachen Würfel (=Skybox), dessen 6 Seiten mit jeweils einer Textur versehen werden. Auf die Oberseite projiziert man den Himmel und an die Unterseite den Boden. Die 4 anderen Seiten stehen für die jeweiligen Himmelsrichtungen.&lt;br /&gt;
Wenn man nun die Skybox zuerst zeichnet und anschließend den [[Tiefenpuffer|Depthbuffer]] löscht, erreicht man, dass die Skybox anschließend immer an den Stellen verdeckt wird, wo sich noch andere [[Fragment]]e der Szene befinden. Dies ist logisch, da gegenüber den Fragmenten der Skybox, die bereits im Framebuffer stehen, alle anderen Fragmente den [[Tiefentest]] bestehen.&lt;br /&gt;
&lt;br /&gt;
Eine Skybox erhält noch wesentlich mehr Realismus, wenn man sie durch dynamische Effekte, wie z.B. Wolken, die sich bewegen oder eine Sonne, die auf- und untergeht, erweitert.&lt;br /&gt;
&lt;br /&gt;
Skyboxen können mit verschiedenen Programmen wie z.B. [[http://www.planetside.co.uk/terragen/|Terragen]] erzeugt werden.&lt;br /&gt;
&lt;br /&gt;
'''Anmerkung:'''&lt;br /&gt;
@SoS: Vielleicht könntest Du hier noch ein Bild einer aufgeklappten Skybox beisteuern. Ich denke da an das aus deinem Tutorial.&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Skybox&amp;diff=307</id>
		<title>Skybox</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Skybox&amp;diff=307"/>
				<updated>2004-07-22T21:32:02Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Wort Sky kommt aus dem Englischen und bedeutet Himmel. Skyboxen werden verwendet, um die Umgebung in 3D-Szenen darzustellen. Dazu zählen z.B. Landschaften im Hintergrund sowie Sonne, Himmel und Wolken. Da diese Orte nur als Kulisse dienen und für den Programmablauf meist ohne Bedeutung sind, verwendet man für deren Darstellung einfache [[Texturen]].&amp;lt;br&amp;gt;&lt;br /&gt;
Sobald man sich in einer Szene jedoch frei bewegen kann, entstehen mehrere Probleme. Zum einen müssen die Texturen so an einander gefügt werden, dass man den Trick nicht durchschaut und erkennt, dass es sich lediglich um Texturen handelt, zum anderen muss sich die Textur stets in gleicher Entfernung vom Beobachter befinden, damit man sich ihr nicht nähern kann. Obendrein darf die Textur jedoch andere Szenenteile, die erreichbar sind, nicht verdecken.&amp;lt;br&amp;gt;&lt;br /&gt;
Im Prinzip ist das Problem recht leicht zu lösen. Für die Darstellung der Umgebung nutzt man einen einfachen Würfel (=Skybox), dessen 6 Seiten mit jeweils einer Textur versehen werden. Auf die Oberseite projiziert man den Himmel und an die Unterseite den Boden. Die 4 anderen Seiten stehen für die jeweiligen Himmelsrichtungen.&lt;br /&gt;
Wenn man nun die Skybox zuerst zeichnet und anschließend den [[Tiefenpuffer|Depthbuffer]] löscht, erreicht man, dass die Skybox anschließend immer an den Stellen verdeckt wird, wo sich noch andere [[Fragment]]e der Szene befinden. Dies ist logisch, da gegenüber den Fragmenten der Skybox, die bereits im Framebuffer stehen, alle anderen Fragmente den Tiefentest bestehen.&lt;br /&gt;
&lt;br /&gt;
Eine Skybox erhält noch wesentlich mehr Realismus, wenn man sie durch dynamische Effekte, wie z.B. Wolken, die sich bewegen oder eine Sonne, die auf- und untergeht, erweitert.&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Hintergrundwissen&amp;diff=386</id>
		<title>Hintergrundwissen</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Hintergrundwissen&amp;diff=386"/>
				<updated>2004-07-22T21:25:22Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was hier hinein gehört ==&lt;br /&gt;
&lt;br /&gt;
In diese Kategorie kommt alles rein was zum Verständnis im Bereich OpenGL/3D-Programmierung nützlich sein könnte. Also u.a. welche Puffer es unter OpenGL gibt, und für was die gut sind.&lt;br /&gt;
&lt;br /&gt;
Auch hier sollte man möglichst aufspalten und dann eine Überschrift setzen. So macht man das Auffinden bestimmter Dinge leichter und auch die Verlinkung darauf ist oft etwas das man in anderen Dokumenten benötigt.&lt;br /&gt;
&lt;br /&gt;
P.S. : Ob hier Deutsche Begriffe oder Anglizismen genutzt werden ist jedem selbst überlassen. Ich persönlich bevorzuge ersteres.&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
&lt;br /&gt;
=== Grundlagen ===&lt;br /&gt;
 [[Primitive]]  &lt;br /&gt;
&lt;br /&gt;
=== Bildentstehung ===&lt;br /&gt;
 [[Fragment]]e&lt;br /&gt;
 [[Pixel]]&lt;br /&gt;
 [[Tiefentest]]&lt;br /&gt;
&lt;br /&gt;
=== Puffer ===&lt;br /&gt;
 [[Akkumulationspuffer]] (Accumulationbuffer)&lt;br /&gt;
 [[Doppelpufferung]] (Doublebuffering)&lt;br /&gt;
 [[Farbpuffer]] (Colorbuffer)&lt;br /&gt;
 [[Framebuffer]]&lt;br /&gt;
 [[Stempelpuffer]] (Stencilbuffer)&lt;br /&gt;
 [[Tiefenpuffer]] (Depthbuffer)&lt;br /&gt;
&lt;br /&gt;
=== Texturen ===&lt;br /&gt;
 [[Multitexturing]]&lt;br /&gt;
 [[Texturen]]&lt;br /&gt;
&lt;br /&gt;
=== Effekte ===&lt;br /&gt;
 [[Antialiasing]] (Kantenglättung)&lt;br /&gt;
 [[Blenden]] (Blending)&lt;br /&gt;
 [[Nebel]] (Foging)&lt;br /&gt;
 [[Transparenz]] (durchsichtige Objekte)&lt;br /&gt;
&lt;br /&gt;
=== Optimierungen ===&lt;br /&gt;
 [[Backfaceculling]]&lt;br /&gt;
 [[Displaylisten]] &lt;br /&gt;
 [[Triangulation]]&lt;br /&gt;
&lt;br /&gt;
=== Fehler/ Nebeneffekte ===&lt;br /&gt;
 [[Aliasing]] - Treppenbildung und Ähnliches&lt;br /&gt;
 [[ZFighting]] - Flimmernde Polygone und Kanten&lt;br /&gt;
&lt;br /&gt;
=== Render-Pipeline ===&lt;br /&gt;
 [[Feste Funktionspipeline]]&lt;br /&gt;
 [[Shader]]&lt;br /&gt;
&lt;br /&gt;
=== Bücher zu diesem Thema ===&lt;br /&gt;
 OpenGL [[RedBook]]&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	<entry>
		<id>https://wiki.delphigl.com/index.php?title=Techniken_und_Algorithmen&amp;diff=311</id>
		<title>Techniken und Algorithmen</title>
		<link rel="alternate" type="text/html" href="https://wiki.delphigl.com/index.php?title=Techniken_und_Algorithmen&amp;diff=311"/>
				<updated>2004-07-22T21:24:08Z</updated>
		
		<summary type="html">&lt;p&gt;Magellan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was hier hinein gehört ==&lt;br /&gt;
Hier kommen, wie der Name vermuten lässt '''Erklärungen''' zu, in der 3D-Echtzeitprogrammierung verwendeten, '''Techniken''' hin. Z.B. verschiedene Schattentechniken, Bump-Mapping, etc.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Hintergrundwissen]] gehört hier nicht rein, also solche Sachen wie ''&amp;quot;was ist ein Tiefenpuffer und wofür ist er gut&amp;quot;'' haben hier nichts zu suchen.&amp;lt;br&amp;gt;&lt;br /&gt;
Sollte es für eine Technik/Thematik (siehe unten für Beispiel) mehrere &amp;quot;Lösungswege&amp;quot; geben, sollte eine kleine Überschrift eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
=== Licht und Schatten ===&lt;br /&gt;
Das Beleuchtungsmodell von OpenGL besitzt von Haus aus keine Möglichkeit zur Darstellung von Schatten (nicht zuletzt weil es dafür immernoch keine einheitliche Methode gibt), allerdings haben sich über die Jahre hinweg einige Techniken mehr oder weniger durchgesetzt :&amp;lt;br&amp;gt;&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Volumetrische Stencilschatten]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Lightmaps]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Projezierte Shadowmaps]]&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Weitere ===&lt;br /&gt;
&amp;lt;li&amp;gt;[[Partikelsysteme]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Skyboxen]]&amp;lt;/li&amp;gt;&lt;/div&gt;</summary>
		<author><name>Magellan</name></author>	</entry>

	</feed>