Texture Skalieren



  • Hey,

    Ich hätte mal eine Frage zum Thema Texturen und der Skalierung.
    Vorweg: Ich nutze C++ und OpenGL.

    Ich habe zurzeit folgendes Problem: Bei einem Objekt (z.B. einem Viereck) habe ich eine 1024x1024 Texture raufgemappt, sollte ich mich nun weiter von dem Objekt entfernen, soll aber nicht mehr eine 1024x1024 Texture sondern z.B. eine 512x512 Texture oder noch kleiner gemappt werden (einfach aus Performancegründen).
    Gibt es eine (performante) Möglichkeit das schnell zu berechnen? Gerade bei größeren Welten mit vielen Objekten wäre das praktisch und ich möchte eig. nicht unbedingt immer unterschiedliche Texturegrößen per Hand anfertigen 🙂



  • Ja, das ganze nennt sich Mip Mapping und ist eine Grundfunktion von OpenGL sowie D3D.

    https://de.wikipedia.org/wiki/Mip_Mapping

    http://wiki.delphigl.com/index.php/MipMaps

    In OpenGL setzt man die entsprechenden Werte der Textur um Mipmaps beim Rendern zu verwenden. Dazu zuerst die Textur binden und dann z.B.

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    

    Seit GL 1.4 ist die Funktion glGenerateMipmap Standard um Mipmaps für eine Textur zu erzeugen. Das geht auch recht fix, da dass die GPU macht.

    glGenerateMipmap(GL_TEXTURE_2D);
    

    Die veraltete Variante mittels des GL_GENERATE_MIPMAP Textur Wertes würde ich empfehlen nicht mehr zu verwenden.

    Die einfachste Art von Mipmap Verwendung nennt sich bilineares Filtern. Eine erweiterte Form mit Übergängen der einzelnen Mipmap Level ist trilineare Filterung. Und dann gibt es noch eine Erweiterung namens Anisotropes Filtern für schräge Blickwinkel.



  • Wieso ist es eigentlich performanter eine 512x512 Texture zu mappen als eine 1024x1024 ?



  • scott schrieb:

    Wieso ist es eigentlich performanter eine 512x512 Texture zu mappen als eine 1024x1024 ?

    Ist es nicht, du sparst nur ein paar KB GPU Memory. Problematisch wird es erst, wenn die Textur so groß ist dass es zu haufenweise Cache Misses kommt (4096^2 Textur wird auf 100^2 Pixeln angezeigt)



  • Hmmm... da hätte ich am Anfang noch etwas drauf eingehen sollen. Mipmaping hat nichts direkt mit Performance zu tun, sondern mit der verwendeten Filtermethode.

    Die einfachste Art eine Information aus einer Textur zu holen ist, sich einfach den Wert des Pixel zu holen welchem man am nächsten ist. Dass nennt sich bei OpenGL -> GL_NEAREST.

    Ein Filter der bessere Ergebnisse liefert ist GL_LINEAR. Dabei werden die vier am nächsten liegenden Pixelwerte genommen und anhand ihrer Entfernung zum Messpunkt ein Mittelwert errechnet.

    So schaut der Unterschied dann aus:
    http://other.paul-grunewald.de/ogl/resources/tutorial/mipmaps.jpg

    Da GL_LINEAR immer genau vier werte liest, funktioniert dass nur solange, wie auch der Messpunkt (also der Bildschirmpixel) nur maximal 4 Pixel der Textur abdeckt. Ansonsten ist eine Art Rauschen zu sehen.

    Werden mehr Textuhrpixeln abgedeckt, z.B. weil eine Textur im 3d raum sehr weit vom Betrachter entfernt ist, müsste man entweder den Mittelwert von mehr als 4 Textuhrpixeln errechnen oder vorausberechnete Mittelwerte haben. Die Grafik Ingenieure haben sich vor langer Zeit einmal für die Zweite Variante entschieden, und diese nennt sich Mipmap.

    Dabei werden einfach kleinere Versionen der Textur erzeugt. Ein Pixel der nächst kleineren Mipmap-Stuffe enthält immer den Mittelwert von 4 Pixeln der vorherigen Stuffe bzw. der Originaltextur.

    Für Mipmaps wird zusätzlicher Grafikspeicher belegt. Das ist jedoch weniger als die Hälfte des Speichers welchen die Textur selber belegt.



  • Gast_0025 schrieb:

    scott schrieb:

    Wieso ist es eigentlich performanter eine 512x512 Texture zu mappen als eine 1024x1024 ?

    Ist es nicht, du sparst nur ein paar KB GPU Memory. Problematisch wird es erst, wenn die Textur so groß ist dass es zu haufenweise Cache Misses kommt (4096^2 Textur wird auf 100^2 Pixeln angezeigt)

    Beim normalen texturieren (ich schätze mal das meint er mit mappen) macht es auf jedenfall nen Unterschied. Und zwar nen gewaltigen. Ne GPU schafft nur ne bestimmte Anzahl an texeln pro Sekunde, und bei ner Größe von 1024x1024 hast du 4 mal so viele texel die gezeichnet werden müssen. Das merkt man schon deutlich.

    Hab da vor langem mal nen Test gemacht. Ich konnte ca. 100 Sprites mit ungefähr 60k fps zeichnen, als die Texturen noch 16x16 groß waren . Beim vergrößern auf 50x50 warens dann auf einmal nur noch 3000 oder so ("nur noch").



  • @TravisG: Ja, wenn man Texel hat die mehr als einen Bildschirmpixel abdecken, dann benötigt man auch weniger Füllrate. Jedoch kämen dann sowieso keinerlei Mipmaps zum Einsatz.

    Auch heutige Mittelklasse Grafikkarten haben schon sehr gute Füllraten. Und wenn du sehr viel auf dem Bildschirm zeichnest kannst du auch relativ einfache Optimierungen anwenden wie early Z rejection, welche dafür sorgt dass die meisten Texel garnicht gelesen werden müssen und somit die Füllrate keinen Flaschenhals darstellt.

    Und "nur" 3000 FPS benötigt sowieso keine Optimierung. 😉

    Mein Tip: Mach dir über die Texturgröße keine Performance-Gedanken. Du musst da eher über den Grafikspeicher nachdenken. 16 4096x4096 Texturen benötigen schon 256MiB VRam wenn sie nicht komprimiert werden. (und Mipmaps noch nicht einberrechnet)
    Für die Bildqualität würde ich auf jeden Fall Mipmaps verwenden. Ansonsten sieht das Rauschen der Textur sehr unschön aus.
    Und wie Gast_0025 auch sagte, würde durch Cache Misses tatsächlich an der Performance geknabbert. (Über Cache Misses habe ich jetzt erst nachgedacht)



  • TravisG schrieb:

    Gast_0025 schrieb:

    scott schrieb:

    Wieso ist es eigentlich performanter eine 512x512 Texture zu mappen als eine 1024x1024 ?

    Ist es nicht, du sparst nur ein paar KB GPU Memory. Problematisch wird es erst, wenn die Textur so groß ist dass es zu haufenweise Cache Misses kommt (4096^2 Textur wird auf 100^2 Pixeln angezeigt)

    Beim normalen texturieren (ich schätze mal das meint er mit mappen) macht es auf jedenfall nen Unterschied. Und zwar nen gewaltigen. Ne GPU schafft nur ne bestimmte Anzahl an texeln pro Sekunde, und bei ner Größe von 1024x1024 hast du 4 mal so viele texel die gezeichnet werden müssen. Das merkt man schon deutlich.

    Hab da vor langem mal nen Test gemacht. Ich konnte ca. 100 Sprites mit ungefähr 60k fps zeichnen, als die Texturen noch 16x16 groß waren . Beim vergrößern auf 50x50 warens dann auf einmal nur noch 3000 oder so ("nur noch").

    Aber wieviel Texel gezeichnet werden bestimmt doch die Rasterisierung des Dreiecks und sollte volkommen unabhängig von der zu mappenden Textur sein ?



  • Bei Mip-Mapping geht's vor allem um die Bildqualität. Wenn eine Texur so extrem verkleinert wird kommts zu Aliasing-Effekten. Mit Mip-Mapping lässt sich das vermeiden...


Anmelden zum Antworten