Spielwiese/Tutorial 4/grey

Aus DGL Wiki
Version vom 2. Dezember 2008, 20:57 Uhr von Grey (Diskussion | Beiträge) (zwischenspeichern)

Wechseln zu: Navigation, Suche

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
BMPGL_RGB
JPG/JPEGGL_RGB / GL_RGBA
PNGGL_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.