Spielwiese/Tutorial 4/grey
Inhaltsverzeichnis
Texturen - Wie kommt die Tapete an die Wand?
Vorwort
Willkommen in der Welt der Bilder! In diesem Tutorial wirst du erfahren, wie man auf ein Polygon (Dreieck, Viereck usw) eine Textur zeichnen kann. Angefangen mit dem
Laden über das einfache Platzieren kommen wir schlussendlich dann dazu, wie man nur einzelne Bereiche einer Textur darstellen kann
(dies ist das sog. UV-Mapping).
Wofür denn überhaupt Texturieren? Ohne ist doch viel schöner ... oder etwa nicht? Nach den letzen Tutorials werden sich vielleicht
einige den Wunsch verspürt haben mehr als nur abstrakte Kunst mit Farben und Farbverläufen darzustellen - dem Wunsch wird hiermit
nachgekommen :D !
Genug geschwafelt, fangen wir mal endlich an.
Crash-Kurs im Tapezieren
Vorbereitung
In dem Ursprünglichen Tutorial hatte Phobeus hatte Tapeten zur Verbildlichung der Materie genutzt und da mir das soweit ganz gut
gefällt will ich das auch beibehalten. Nun, am Besten fangen wir mit einem möglichst praktischen Beispiel an. Stell dir vor dein Polygon sei deine Wand und die Textur ist
deine Tapete. Wer sich nun denk - Yeah ich hab ne 12 Megapixel Cam - das gibt geile Texturen, dem kann ich nur zustimmen und dabei den
Kopfschütteln. Klar ist so nen Bild ne geile Textur - wenn du nur eine Textur Verwenden willst, dann geht das vielleicht noch, aber
sobald du einen eigenen Level erstellen möchtest wird dir auffallen wie gigantisch auch der Speicherverbrauch und wie schlecht die
Performance davon ist. Also heißt es erstmal zurecht schneiden. Was Texturen angeht ist OpenGl leider wählerisch - es nimmt nur Texturen im Format 2^n x 2^n also z.B. 16x16, 64x64 aber auch 16x1024 oder 32x64 usw. (Ausnahmen sind möglich, werden in diesem Tutorial aber nicht behandelt)
Mit unserem überdimensionierten Tapetenmesser haben wir nun unsere Tapete (Textur) in die Richtige Form gebracht - Jetzt gilt es sie
mit Kleister zu versehen(Laden) und auf den Tapeziertisch(Grafikspeicher) zu legen, damit wir sie dann auch schnell an die Wand
bekommen.
Laden der Textur
Okay, wir haben unsere Textur jetzt zurecht geschnitten und auf unserer Festplatte abgelegt - doch wie kommt sie jetzt von da in den
Grafikspeicher? Wer mal mit den standart I/O-Methoden von Delphi rumgespielt hat weiß, dass es nicht immer einfach ist an die
gewünschten Daten in einer Datei zu kommen - daher will ich jetzt auch niemanden damit quälen, denn wir haben ja die SDL, welche
bereits fertige Methoden zum einlesen von Bilddaten besitzt. Nehmen wir uns jetzt einfach ein frisches ungebrauchtes easySDL Template und spielen damit etwas rum. Als erstes machen wir bekannt, das wir eine neue Prozedur haben (und erstellen in dem Zug gleich auch die Variable in der die Textur
gespeichert werden soll).
type TMyProgram=class(TEasySDL) texture : gluInt; //Hier wird die Textur gespeichert procedure DrawScene;override; //Hier wird die Scene gezeichnet procedure LoadTexture; //Hier wird die Texur geladen end;
Und jetzt laden wir die Textur:
procedure TMyProgram.LoadTexture; var tex : PSDL_Surface; //Zwischenspeicher für die Textur begin tex := IMG_Load('./wall.jpg'); //Laden der Textur if assigned(tex) then begin glGenTextures(1, @texture); {1} glBindTexture(GL_TEXTURE_2D, texture); {2} glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);{3} glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, tex^.w, tex^.h,0, GL_RGB, GL_UNSIGNED_BYTE, tex^.pixels); {4} // Achtung! Einige Bildformate erwarten statt GL_RGB, GL_BGR. Diese Konstante fehlt in den Standard-Headern SDL_FreeSurface(tex); end; end;
Obwohl ich dich jetzt nicht für den DAU halte erkläre ich grade mal den Programablauf in Worten:
1.Zwischenspeicher für die Textur erstellen
2. Bilddatei in den Zwischenspeicher laden
3. OpenGL sagen, das wir eine Textur erstellen möchten (1) wobei der erste Parameter für die Anzahl der zu erstellenden Texturen steht und der Zweite für die Adresse der Variable.
4. Dann teilen wir OpenGL mit (2), dass sich von nun an alle Änderungen und Anweisungen, die sich auf Texturen beziehen auf die Textur "texure" beziehen, sowie das diese eine 2D-Textur ist.
5. Dann setzen wir noch ein paar Texturfilter (3) (näheres darüber gibts im Tutorial Blending).
6. Jetzt endlich wird die Textur in den Grafikspeicher eingeladen. 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.
Welches Farbformat dein Bildformat verwendet kannst du meist auf Wikipedia nachschlagen, dennoch will ich hier mal die am häufigsten genutzten Auflisten:
Dateiformat | Farbformat |
---|---|
BMP | GL_RGB |
JPG/JPEG | GL_RGB / GL_RGBA |
PNG | GL_RGB / GL_RGBA |
Sollte jetzt irgendjemand den Drang verspüren eine Ausführlichere Übersicht zu erstellen, so sei er dazu herzlich eingeladen und möge dies dann doch bitte im Forum (oder gleich im Wiki) posten.
Tapeten an die Wand!
So, jetzt ist die Textur endlich da wo wir sie haben wollen, doch was nun? - Ganz einfach wir nehmen die Textur und kleben sie auf ein Viereck. Doch bevor wir anfangen muss (wie fast überall) mal wieder etwas aktiviert werden - und, wer hätte es erraten - es ist die Texturierung, die wir mit glEnable() einschalten müssen, doch am besten erkläre ich das mal an folgendem Beispiel:
procedure TMyProgram.DrawScene; begin glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT); glLoadIdentity; gltranslatef(0,0,-5); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,texture); glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex3f(-1,-1,0); glTexCoord2f(0,1); glVertex3f(-1,1,0); glTexCoord2f(1,1); glVertex3f(1,1,0); glTexCoord2f(1,0); glVertex3f(1,-1,0); glEnd; glDisable(GL_TEXTURE_2D); end;
|
||
Vorhergehendes Tutorial: Tutorial Lektion 3 |
Nächstes Tutorial: Tutorial Lektion 5 |
|
Schreibt was ihr zu diesem Tutorial denkt ins Feedbackforum von DelphiGL.com. Lob, Verbesserungsvorschläge, Hinweise und Tutorialwünsche sind stets willkommen. |