Tutorial TexFilter: Unterschied zwischen den Versionen
Flash (Diskussion | Beiträge) K (→Mipmaping: 4Bilder pro Zeile -> 2x2Bilder pro Zeile) |
Flash (Diskussion | Beiträge) K (→Texture Compression) |
||
Zeile 165: | Zeile 165: | ||
[[Kategorie:Tutorial|TexturFiltering]] | [[Kategorie:Tutorial|TexturFiltering]] | ||
− | {{TUTORIAL_NAVIGATION| | + | {{TUTORIAL_NAVIGATION|[[Tutorial Selection]]|-}} |
Version vom 27. September 2005, 13:49 Uhr
Inhaltsverzeichnis
Texturen-Feintuning
Einführung
Hi, eigentlich wollte ich ja nur ein Sample über Texture Compression schreiben. Als ich Phobeus davon erzählt habe, hat er mir nahegelgt, doch gleich ein ganzes Tutorial über Texture Filter, etc. zu schreiben. Ich hab mich dazu breitschlagen lassen*g*. Es lässt sich nicht ganz umgehen, dass ich hier ein paar Basics zu den Tapeten wiederholen muss, aber ich denke das könnt ihr verkraften.
Texturen filtern
Filtern? Ein etwas ungewöhlicher Ausdruck für 3D Grafik. Kaffe kann man filtern, aber Texturen? Texturen sind gewöhnlich Quadrate oder Rechtecke. Wird ein Polygon, über das eine Textur geklebt ist, auf dem Bildschirm angezeigt, so entsprechen oft mehrere Texel einem Pixel(Minification) oder nur Teile eines Texels einem Pixel(Magnification):
Für Beide Fälle stehen zwei Filtermethoden zur Verfügung:
GL_NEAREST
- Einem Pixel wird genau das Texel zugewiesen, dass dem Zentrum des Pixels am nächsten liegt. Dies führt häufig zu Bildschirmartefakten, ist aber die schnellere der beiden Varianten.
GL_LINEAR
- Dem Pixel wird der Durchschnitt eines 2x2 Arrays von Texeln, die dem Zentrum des Pixels am nächsten liegen, zugewiesen. Dies führt zu einem weicheren Ergebnis, ist aber auf den meisten OpenGL Geräten langsamer.
Wie wird nun aber ein Filter auf eine Textur angewendet? Nachdem eine Textur mit glBindTexture ausgewählt wurde, werden ihr mittels glTextParameteri die unterschiedlichen Filter zugewisen:
glBindTexture(GL_TEXTURE_2D, DemoTexture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
Das Beispielt wählt für die DemoTextur den MAGnification Filter nearest und für den MINification Filter linear.
Filterergebnisse einer 8x8 Schachbrettextur(links: linear, rechts: nearest):
Filterergebnisse einer bunten Textur
Mipmaping
Mipmaps sind eine Art Level of Detail für Texturen. Die Seitenlänge der Originaltextur wird halbiert und dann als eigenes Bild im Speicher abgelegt. Das gleiche geschieht mit dem halbiertem Bild, bis nur noch eine Textur der größe 1x1 übrig bleibt. Wird nun eine Textur in großer Entfernung angezeigt, wird von der Textur eine kleinere Version gewählt, als wenn die Textur nur wenig Abstand zur Kamera hat. Dadurch kann die Bildqualität erheblich verbessert werden.
Zum erstellen der Mipmaps kommt in OpenGL meist gluBuild2DMipmaps zum Einsatz. Wird DevIL verwendet, hilft einem diese Funktion meist wenig(bei Texture Compression zeige ich wies trotzdem geht), besonders wenn Paletten zum Einsatz kommen. Hier gibt es die Funktion ilutGLBuildMipmaps. Beispielsweise ließen sich mit folgender Funktion Texturen laden:
function LoadDevILTexture(Filename : String): TGLUInt; var id:TILInt; begin {$T-} // Laden eines Texture in den Speicher ilGenImages(1, @id); ilBindImage(id); ilLoadImage(PChar(Filename)); // Übergeben der Texture an OpenGL Result := ilutGLBindMipmaps; glBindTexture(GL_TEXTURE_2D, Result); {Hier könnten die Filteroptionen stehen} // Da OpenGL die Texture hat, können wir sie aus dem Speicher entfernen ilDeleteImages(1, @Id); {$T+} end;
Achtung:DevIL muss vor dem erstmaligem Aufruf noch initialisiert werden:
ilInit; ilutRenderer(IL_OPENGL);
Nun stehen für den Minification Filter folgende neue Funktionen zur Verfügung: GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST und GL_LINEAR_MIPMAP_LINEAR. Ergebnisse in genau dieser Reihenfolge, wobei der Magnification Filter bei allen auf nearest gesetzt ist:
Texture Compression
Hinter Texture Compression versteckt sich etwas sehr interessantes. Um Grafiken für das Web benutzen zu können, werden sie häufig komprimiert(z.B. JPEG), damit sie weniger Platz beanspruchen. Das Gleiche gibt es Unter OpenGl. Hier steht schließlich nicht unendlich viel Platz im Grafikkartenspeicher zur Verfügung. Wenn man also auch hier die Texturen komprimiert, dann kann man wesentlich mehr Texturen unterbringen. Nebenbei wird die Sache auch noch schneller, da beim Zugriff auf die Textur weniger Daten über den Bus laufen müssen. Möglich wird Texture Compression unter OpenGL durch eine Extension namens GL_ARB_TEXTURE_COMPRESSION. Um herauszufinden ob diese Extension vorliegt, müssen wir OpenGL12 anweisen, alle Extensions auszulesen:
ClearExtensions; ReadExtensions;
Gewöhlich geschieht dies nach dem setzten des Pixelformats, etc. aber noch vor dem Laden irgendwelcher Texturen. Ist jetzt GL_ARB_texture_compression auf true gesetzt, können wir Texturkompression verwenden. Wenn an OpenGL die Texturdaten mittels glTexImage2D die Bilddaten übergeben werden, muss nun einfach als internalformat nicht GL_RGB angegeben werden, sondern GL_COMPRESSED_RGB_ARB. Klingt sehr simpel... Für DevIL müssen wir uns noch etwas spezielles einfallen lassen, denn wenn die Daten mithilfe einer Palette dargestellt werden bringen sie wenig. Sie müssen vorher konvertiert werden:
function LoadDevILTextureCompressed(Filename : String): TGLUInt; var id:TILInt; imageInfo : TILInfo; Data : PILUByte; compressed : Integer; begin if not GL_ARB_texture_compression then LoadDevILTexture(Filename); {$T-} // Laden einer Texture in den Speicher ilGenImages(1, @id); ilBindImage(id); ilLoadImage(PChar(Filename)); // Loads into the current bound image //Wir brauchen das Bild als IL_RGB oder IL_RGBA ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); // Übergeben der Texture an OpenGL iluGetImageInfo(@ImageInfo); Data := ilGetData(); glGenTextures(1, @Result); glBindTexture(GL_TEXTURE_2D, Result); //einfache textur glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_ARB, ImageInfo.Width, ImageInfo.Height, 0, GL_RGB, GL_UNSIGNED_BYTE, Data); //oder für mipmaps: //gluBuild2DMipmaps(GL_TEXTURE_2D, // GL_COMPRESSED_RGB_ARB, // ImageInfo.Width, ImageInfo.Height, // GL_RGBA, GL_UNSIGNED_BYTE, Data); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, @compressed); if compressed <> 1 then MessageDlg('Texture wurde nicht komprimiert', mtError, [mbOk], 0); {Filteroptionen} ilDeleteImages(1, @Id); {$T+} end;
IL_RGB und GL_RGB können bei bedarf durch IL_RGBA und GL_RGBA ausgetauscht werden. Werden Mipmaps benötigt, so muss einfach vor gluBuild2DMipmaps die Kommentare gelöscht werden. Dem geübten Auge werden sicherlich die komprimierten Schmankerl auffallen, bewegt sich aber die Szenerie sehr schnell, wird es niemandem mehr auffallen:
Euer
- Delphic
|
||
Vorhergehendes Tutorial: Tutorial Selection |
Nächstes Tutorial: - |
|
Schreibt was ihr zu diesem Tutorial denkt ins Feedbackforum von DelphiGL.com. Lob, Verbesserungsvorschläge, Hinweise und Tutorialwünsche sind stets willkommen. |