Warum sind Texturen immer quadratische Zweierpotenzen? Was ist, wenn sie nicht sind?

53

Warum ist die Auflösung von Texturen in Spielen immer eine Zweierpotenz (128x128, 256x256, 512x512, 1024x1024 usw.)? Wäre es nicht klug, die Dateigröße des Spiels zu speichern und die Textur genau auf das UV-Modell abzustimmen?

Was würde passieren, wenn es eine Textur gäbe, die keine Zweierpotenz wäre?

Wäre es falsch, wenn eine Textur etwa 256x512 oder 512x1024 wäre? Oder würde dies die Probleme verursachen, die durch Nicht-Zweierpotenz-Texturen verursacht werden können?

Keavon
quelle
9
Ihre anderen Beispiele sind ebenfalls Zweierpotenzen, nur nicht dieselbe Zweierpotenz. Durch die Potenzen von zwei wird die Textur für die Grafikhardware optimiert.
MichaelHouse
1
@Byte56 Ich denke, er bedeutet 2 ^ nx 2 ^ n Textur, wobei n von 1 bis unendlich variiert. (Nicht wirklich unendlich.)
Robin
Beachten Sie auch, dass Zweierpotenzen den Vorteil haben, dass Mipmaps trivial sind.
Pubby
Da die Textur normalerweise umbrochen wird (obwohl Sie dies in einem benutzerdefinierten Shader auswählen können), müssen Sie keinen Platz verschwenden. Wickeln Sie einfach Ihre Polygon-UV-Koordinaten um die Kanten, und Sie können den verfügbaren Platz viel einfacher nutzen. Wenn Sie kein Pressing haben, ist es am sichersten, sich an width = height = 2 ^ n Texturen zu halten, da dies eine größere Auswahl an Hardware auf Kosten eines etwas komplizierteren UV-Layouts ermöglicht.
Daniel Carlsson
Sie sind nicht immer Zweierpotenzen.
Almo

Antworten:

49

Warum ist die Auflösung von Texturen in Spielen immer eine Zweierpotenz (128x128, 256x256, 512x512, 1024x1024 usw.)?

Wie in Byte56 impliziert, bestehen die Größenbeschränkungen für "Zweierpotenzen" darin, dass jede Dimension unabhängig eine Zweierpotenz sein muss und nicht, dass Texturen quadratisch sein müssen und Dimensionen haben müssen, die Zweierpotenzen sind.

Bei modernen Karten und welchen modernen Grafik-APIs wurde diese "Einschränkung" jedoch erheblich gelockert, sodass die Texturdimensionen innerhalb eines vernünftigen Rahmens so gut wie alles sein können, was Sie möchten. Jedoch:

Wäre es nicht klug, die Dateigröße des Spiels zu speichern und die Textur genau auf das UV-Modell abzustimmen? Was würde passieren, wenn es eine Textur gäbe, die keine Zweierpotenz wäre?

Indem sichergestellt wird, dass die Texturdimensionen eine Zweierpotenz haben, kann die Grafikpipeline Optimierungen in Bezug auf die Effizienz beim Arbeiten mit Zweierpotenzen nutzen. Zum Beispiel kann es schneller sein (und war vor einigen Jahren, bevor wir dedizierte GPUs und äußerst clevere Optimierungscompiler hatten), zu dividieren und mit Zweierpotenzen zu multiplizieren. Das Arbeiten mit Zweierpotenzen vereinfacht auch Vorgänge innerhalb der Pipeline, z. B. das Berechnen und Verwenden von Mipmaps (eine Zahl mit Zweierpotenzen wird immer gleichmäßig in zwei Hälften geteilt, sodass Sie sich nicht mit Szenarien befassen müssen, in denen Sie runden müssen Ihre Mipmap-Dimensionen nach oben oder unten).

Es ist wahr, dass Sie auf diese Weise Speicherplatz "verschwenden", aber der zusätzliche Speicherplatz lohnt sich normalerweise für den Kompromiss bei der Renderleistung. Darüber hinaus gibt es Techniken wie das Komprimieren oder Packen mehrerer Bilder in einen einzelnen Texturraum, mit denen ein Teil des Speichermülls eingespart werden kann.

Josh
quelle
11
"Es ist wahr, dass Sie auf diese Weise Speicherplatz" verschwenden ", aber der zusätzliche Speicherplatz lohnt sich normalerweise für den Kompromiss bei der Renderleistung." - Vor ungefähr zehn Jahren arbeitete ich in einem Studio, das ein PS2-Spiel auf die XBox portierte. Obwohl die PS2 technisch keine Texturen unterstützt, die nicht der Potenz von zwei entsprechen, können Sie sie in einigen Fällen mit ein wenig cleverer Manipulation und ohne Geschwindigkeitsverlust dazu zwingen. Die XBox hingegen hat sie überhaupt nicht unterstützt. Das Endergebnis ist, dass wir, obwohl die XBox fast doppelt so viel RAM hat wie die PS2, einige Texturen herunterrechnen mussten, um sie anzupassen.
ZorbaTHut
Es fällt mir schwer, ein Zitat zu finden, aber ich habe zuvor gelesen, dass JPEG-Bilder für maximale Effizienz ein Vielfaches von 8 sein sollten, da für alles andere noch ein 8x8-Block erforderlich ist.
Lachs Elch
1
@salmonmoose: Richtig; JPEG komprimiert jeden 8x8-Block unabhängig und füllt die Blöcke am Rand auf. Aber das hat nichts mit dieser Frage zu tun.
MSalters
1
JPEGs werden in 8x8-Blöcken codiert, ja. Das ist jedoch kein wirklicher Effizienzaspekt. Und es ist auch nicht unbedingt eine Potenz von 2. :)
Kylotan
Ein Beispiel ist auf Android, wo oft nicht-Power-Zwei-Texturen zu weißen Texturen führen.
User717572
17

Warum sind Texturen immer quadratische Zweierpotenzen?

Texturen sind nicht immer quadratisch und nicht immer Potenzen von zwei . Der Grund, warum sie in der Regel Zweierpotenzen sind, ist die höhere Kompatibilität mit älteren Grafikkarten, die diese Einschränkung auferlegt haben. Bei nicht quadratischen Texturen ist dies normalerweise kein Problem. Zusammenfassen:

  • Texturen müssen in der Regel nicht quadratisch sein - obwohl DirectX über eine D3DPTEXTURECAPS_SQUAREONLYFunktion verfügt, habe ich auch mit älterer Hardware problemlos mit nicht quadratischen Texturen gearbeitet.
  • Texturen sollten Zweierpotenzen sein, da viele ältere Grafikkarten dies noch benötigen. Der Grund für diese Einschränkung war, dass sie einige Optimierungen an den Texturabbildungsoperationen durchführen konnten. Die meisten modernen Grafikkarten haben diese Einschränkung ebenfalls nicht.
David Gouveia
quelle
12
Es sollte beachtet werden, dass mit "älteren Grafikkarten" Sachen gemeint sind, die vor 2006 oder so entstanden sind.
Nicol Bolas
1
@NicolBolas Danke, ich habe tatsächlich versucht, einige Referenzen zu diesem Punkt zu finden.
David Gouveia
7

Es bezieht sich auf Grafikkartenoptimierungen. Sie wurden entwickelt, um sie auf diese Weise zu verarbeiten. Die meisten Karten in diesen Tagen wird können Sie Texturen mit Dimensionen laden , die nicht Potenzen von zwei sind, aber es wird wahrscheinlich einen negativen Einfluss auf die Leistung haben. Es besteht eine gute Chance, dass das Laden tatsächlich konvertiert wird, was Sie Zeit kostet und keinen Speicher spart. Nicht quadratische Texturen sind im Allgemeinen in Ordnung, solange beide Dimensionen Potenzen von zwei sind.

Eine Möglichkeit, mit Texturen ungerader Größe umzugehen, ist die Verwendung eines Texturatlas . Grundsätzlich fügen Sie mehrere Texturen zu einer einzigen Textur zusammen und verwenden die Texturkoordinaten Ihrer Scheitelpunkte, um auf das gewünschte Bild zu verweisen. Dies bringt zusätzliche Leistungsvorteile mit sich, da Zustandsänderungen vermieden werden können. In der Regel werden dabei alle Elemente der Benutzeroberfläche in einer einzigen Textur angeordnet. Wenn Sie also die Eckpunkte der Benutzeroberfläche in einem einzigen Pufferobjekt zusammengefasst haben, können Sie das Ganze mit einem einzigen Aufruf zeichnen, anstatt die Texturen zu wechseln viele Male und machen einen separaten Draw Call für jeden.

Jason Morales
quelle
6

Das Problem ist, dass manche Hardware nur eingeschränkte Unterstützung für Texturen bietet, die keine zweidimensionale Potenz haben.

Sehen Sie sich beispielsweise unten http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876%28v=vs.85%29.aspx an und lesen Sie dort die Fußnoten 3 und 4.

3 Auf den Merkmalsebenen 9_1, 9_2 und 9_3 unterstützt das Anzeigegerät die Verwendung von 2D-Texturen mit Dimensionen, die unter zwei Bedingungen keine Zweierpotenzen sind. Erstens kann nur eine MIP-Map-Ebene für jede Textur erstellt werden, und zweitens sind keine Wrap-Sampler-Modi für Texturen zulässig (das heißt, die Mitglieder AddressU, AddressV und AddressW von D3D11_SAMPLER_DESC können nicht auf D3D11_TEXTURE_ADDRESS_WRAP festgelegt werden).

4 Auf den Feature-Levels 10_0, 10_1 und 11_0 unterstützt das Anzeigegerät die Verwendung von 2D-Texturen mit Dimensionen, die keine Zweierpotenzen sind.

Adam
quelle
6

Grafikhardware ist für Matrixoperationen, Fragmentoperationen und Vektoroperationen optimiert. Einfach ausgedrückt, quadratische Matrizen sind einfacher zu handhaben, da Berechnungen in Blöcken (als Fragmente bezeichnet) durchgeführt werden können. Die Hardware ist für Blockoperationen optimiert. Deshalb gibt es beispielsweise Dateipuffer. Das RAM-Blit wird erst nach einem Block auf die Festplatte übertragen wurde besiedelt. Gleiches gilt für den Grafikspeicher.

Der Einzelbildpuffer besteht aus Fragmenten, die quadratisch sind. In einem Bildschirm mit einer Auflösung von 800 x 600 und einem RGB-Farbraum (0 bis 255) gibt es beispielsweise 800 x 600 Punkte mit 3 Bytes pro Kanal. Im Bildspeicher müssen insgesamt 3 x 800 x 600 = 1.440.000 Bytes adressiert werden. Das heißt, es gibt 1.875 adressierbare Fragmente mit einer Größe von 256 x 256 x 3 Byte. Da die Texturdaten quadratisch sind, ist die Zuordnung von der GRAM-Matrix zur Bildschirmpuffermatrix mithilfe der bikubischen Skalierung erheblich einfacher. Wenn die Verzerrung für die längere Seite nicht quadratisch wäre, würde die Berechnung bei Bedarf mehr Zeit in Anspruch nehmen skaliert werden.

Viele Grafik-APIs akzeptieren nicht quadratische Texturdaten, da sie UV-Zuordnungskoordinaten als Gleitkommadaten akzeptieren. Sobald sie an die GPU gesendet werden, werden die Texturdaten jedoch aufgefüllt, da die tatsächlichen Bildanteile die Zuordnung nicht ändern scheint nicht betroffen zu sein, jedoch werden die Texturdaten aufgefüllt, da die GPU sie gerne als perfektes Quadrat anspricht.

Wenn also ein Bild mit einer Größe von 100 x 1024 und ein Bild mit einer Größe von 1024 x 1024 verwendet wird, gehen 946.176 Byte verloren. Dies gilt umso mehr, wenn zusammengesetzt werden soll, da ein Alpha-Kanal hinzugefügt werden muss, um anzuzeigen, dass die Fülldaten die zusammengesetzte Textur nicht beeinflussen sollen.

awiebe
quelle
Dies ist eine interessante Erklärung (Leckerbissen über quadratische Matrizen), die nicht in der üblichen Potenz von 2 Antworten (+1) zu finden ist - könnten Sie wenn möglich einige Zitate angeben?
Samaursa
1

Unsere digitale Welt arbeitet mit binärer Nummerierung, um dann einen Wert zu multiplizieren oder durch 2 zu teilen. Sie können einen Wert nach links oder rechts "verschieben", dh

<<  Left shift      x = 5 << 1    0101 << 1     1010     10
>>  Right shift     x = 5 >> 1    0101 >> 1     0010      2

Das Arbeiten mit Werten "Zweierpotenz" ist für eine CPU einfacher.

Esdebon
quelle
0

Moderne Hardware kommt (endlich) damit zurecht, Wrap-Modi für nicht-leistungsfähige zwei-basierte Texturen zu aktivieren. Nicht-leistungsfähige zwei Texturen verschwenden jedoch immer noch GPU-Speicher, da sie dazu neigen, entlang der Breite um eine hardwarespezifische Menge (entweder) aufgefüllt zu werden auf eine Kachelgröße oder aufgerundet auf die nächste Potenz von zwei Größen, die die Textur enthalten).

Da dies hardwareabhängig ist und die Hersteller im Allgemeinen nicht auf die Einzelheiten dieser Details eingehen, ist es am sichersten, weiterhin zweidimensionale Leistung für Texturen zu verwenden, um keinen GPU-RAM zu verschwenden.

Zoner
quelle