Wie werden Mipmap-Ebenen in Metal berechnet?

14

Meine Frage bezieht sich speziell auf Metal, da ich nicht weiß, ob sich die Antwort für eine andere API ändern würde.

Was ich bisher zu verstehen glaube, ist Folgendes:

  • Eine Mip-Map-Textur hat vorberechnete "Detailebenen", bei denen niedrigere Detailebenen erzeugt werden, indem die ursprüngliche Textur auf eine sinnvolle Weise heruntergesampelt wird.

  • Auf Mipmap-Ebenen wird in absteigender Detailebene Bezug genommen, wobei Ebene 0die ursprüngliche Textur ist und höhere Ebenen eine Potenz-aus-zwei-Reduktion derselben sind.

  • Die meisten GPUs implementieren eine trilineare Filterung, bei der für jedes Sample zwei benachbarte Mipmap-Ebenen ausgewählt, Samples von jeder Ebene mit bilinearer Filterung abgetastet und diese Samples dann linear gemischt werden.

Was ich nicht ganz verstehe, ist, wie diese Mipmap-Ebenen ausgewählt werden. In der Dokumentation für die Metal-Standardbibliothek sehe ich, dass Proben mit oder ohne Angabe einer Instanz eines lod_optionsTyps entnommen werden können . Ich würde annehmen, dass dieses Argument die Auswahl der Mipmap-Ebenen ändert und es anscheinend drei Arten von lod_options2D-Texturen gibt:

  • bias(float value)
  • level(float lod)
  • gradient2d(float2 dPdx, float2 dPdy)

Leider wird in der Dokumentation nicht erläutert, was diese Optionen bewirken. Ich kann mir vorstellen, dass bias()einige automatisch gewählte Detaillierungsgrade voreingenommen sind, aber was bedeutet dann die Voreingenommenheit value? Auf welcher Skala arbeitet es? In ähnlicher Weise wird die lodvon level()in diskrete Mipmap-Ebenen übersetzt? Und unter der Annahme, dass gradient2d()der Gradient der Texturkoordinate verwendet wird, wie wird dieser Gradient zur Auswahl des Mipmap-Levels verwendet?

Noch wichtiger ist, wenn ich das weglasse lod_options, wie werden dann die Mipmap-Ebenen ausgewählt? Unterscheidet sich dies je nach Art der ausgeführten Funktion?

Und wenn die standardmäßige, von no lod options festgelegte Operation der sample()Funktion so etwas wie gradient2D()(zumindest in einem Fragment-Shader) ist, werden einfache Bildschirmableitungen verwendet oder es wird direkt mit Rasterizer- und interpolierten Texturkoordinaten gearbeitet man eine genaue Steigung berechnet?

Und wie konsistent ist dieses Verhalten von Gerät zu Gerät? Ein alter Artikel (alt wie in DirectX 9), den ich gelesen habe, bezog sich auf komplexe gerätespezifische Mipmap-Auswahl, aber ich weiß nicht, ob die Mipmap-Auswahl auf neueren Architekturen besser definiert ist.

lcmylin
quelle

Antworten:

17

Die Mip-Auswahl ist heute geräteübergreifend ziemlich standardisiert - mit Ausnahme einiger Details der anisotropen Filterung, die noch von den einzelnen GPU-Herstellern festgelegt werden müssen (und deren genaue Details im Allgemeinen nicht öffentlich dokumentiert werden).

Ein guter Ort, um mehr über die MIP-Auswahl zu erfahren, ist die OpenGL-Spezifikation, Abschnitt 8.14, "Texture Minification" . Ich würde annehmen, dass es im Metal genauso funktioniert. (Apple hätte etwas ändern können, wenn man bedenkt, dass sie sowohl die Hardware als auch die API herstellen ... aber ich bezweifle, dass dies der Fall ist.) Ich fasse es hier zusammen.

Die Standard-Mip-Auswahl (ohne die lod_optionsModifikatoren) verwendet die Gradienten der Texturkoordinaten im Bildschirmbereich, um die Mip-Ebenen auszuwählen. Im Wesentlichen wird versucht, die Mip-Level auszuwählen, die einer 1: 1-Zuordnung von Texeln zu Pixeln möglichst nahe kommen. Wenn die Farbverläufe beispielsweise eine Länge von 4 Texeln pro Pixel haben, wird MIP-Ebene 2 ausgewählt (was 1/4 der Größe von Ebene 0 entspricht und daher 1 MIP-Texel pro Pixel ergibt).

Da Sie bei der trilinearen Filterung normalerweise nicht auf einer exakten 1: 1-Zuordnung landen , werden die beiden nächstgelegenen Ebenen ausgewählt und linear interpoliert, sodass Sie einen reibungslosen Übergang zwischen MIP-Ebenen erhalten, wenn sich die Kamera oder die Objekte in Ihrer Szene bewegen um.

λλλλ=2.8

λLog2(1/4)=-2

Nun zu den Modifikatoroptionen:

  • biasλ
  • levelλλlod
  • gradient2dMit dieser Option können Sie eigene Verlaufsvektoren einfügen, die die impliziten Rastergradienten der Texturkoordinaten ersetzen. Der Rest des MIP-Auswahl- und Abtastprozesses verläuft normal, jedoch mit den geänderten Gradienten. Auf diese Weise können Sie die anisotrope Filterung anpassen.

Bei anderen Shadertypen als Fragment-Shadern gibt es keine Vorstellung von "Screen-Space-Verläufen", daher sind in der Regel nur die beiden letzteren Operationen zulässig. Jede Operation, die versucht, implizite Verläufe zu verwenden, würde einen Kompilierungsfehler ergeben. Ich bin mir nicht sicher, wie Metal das macht, aber das würde ich von der Arbeit mit anderen APIs erwarten.

Nathan Reed
quelle