Wie erkennt man, welche OpenGL-Texturformate nativ unterstützt werden?

10

Wie kann ich beispielsweise feststellen, ob meine Videokarte "bgr8" nicht unterstützt, und sie in ein anderes Format konvertieren, z. B. "rgba8" im Softwaremodus?

UPDATE: Entschuldigung für die Verwirrung. In dieser Frage geht es mehr um die Situation, wenn ich internalFormat in glTexImage2D auf "bgra8" setze, aber Videodriver Daten intern in ein anderes Format wie "rgba8" konvertiert.

KindDragon
quelle

Antworten:

11

Ihre Frage scheint bestimmte Konzepte zu verwirren. Nehmen wir also die Dinge von oben. Dies ist die Definition der Funktion glTexImage2D:

void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data );

Es gibt zwei Dinge, die Sie als "Texturformate" bezeichnen könnten. Der erste ist der internalformatParameter. Dies ist das tatsächliche Format des Bildes, wenn OpenGL es speichert. Der formatParameter beschreibt einen Teil des Formats der Pixeldaten, die Sie mit dem dataParameter bereitstellen .

Anders ausgedrückt formatund typedefinieren Sie, wie Ihre Daten aussehen. internalformatSo weisen Sie OpenGL an , Ihre Daten zu speichern . Nennen wir formatund typedas "Pixelübertragungsformat", während internalformatdas "Bildformat" sein wird.

Das Bildformat einer Textur kann niemals "bgr8" sein. Es gibt keinen GL_BGR8-Bildformat-Enumerator. Es gibt eine GL_BGR-Aufzählung, aber das gilt für das Pixelübertragungsformat, nicht für das Bildformat.

Oder anders ausgedrückt: Ihre Pixeldaten, die Sie OpenGL geben, können in der BGR-Reihenfolge gespeichert werden. Die OpenGL-Implementierung entscheidet jedoch selbst, wie diese Pixeldaten tatsächlich gespeichert werden. Vielleicht speichert es es in Little-Endian-Reihenfolge. Vielleicht speichert es Big-Endian. Vielleicht ordnet es die Bytes nur willkürlich neu. Sie wissen es nicht und OpenGL bietet keine Möglichkeit, dies herauszufinden.

Es kann nicht festgestellt werden, ob ein bestimmter Satz von Parametern für das Pixelübertragungsformat mit der Art und Weise übereinstimmt, in der die OpenGL-Implementierung sie angesichts des Bildformats speichert.

Es gibt eine Möglichkeit , dies jetzt zu sagen. Und mit "jetzt" meine ich in OpenGL 4.3 und / oder ARB_internalformat_query2. Kommen zu einer Grafikkarte in Ihrer Nähe:

GLenum format, type;
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_FORMAT, 1, &format);
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1, &type);

formatund typejetzt haben die Implementierung bevorzugt formatund typefür die Verwendung von glTex(Sub)ImageAufrufen zu GL_RGBA8Bildern. Es gibt separate formatund typeAbfragen zum glReadPixelsHerunterladen.

Es gibt andere Fragen, die Sie stellen können .

Wenn Sie keinen Zugriff auf diese haben, können Sie einige allgemeine Faustregeln verwenden, die von der meisten Hardware eingehalten werden:

  • speichert Pixeldaten für 8-Bit-pro-Kanal-Daten in BGRA-Reihenfolge. Wenn Sie also das Format mit Ihren Pixeldaten abgleichen möchten, um Texturdaten schneller hochzuladen, möchten Sie es GL_BGRAfür das formatund GL_UNSIGNED_INT_8888oder GL_UNSIGNED_BYTEfür das verwenden type.
  • speichert 24-Bit-Farben nicht als 24-Bit. Sie werden immer auf 32 Bit aufgefüllt. Das Alpha wird beim Lesen der Daten einfach ignoriert. Wenn Sie also Formate abgleichen möchten, verwenden Sie diese immer GL_BGRA formatmit GL_RGB8Bildformaten, auch wenn Sie Dummy-Daten in die Alpha-Komponente einfügen müssen.
Nicol Bolas
quelle
4
Ich fand auch besser das Format GL_BGRA mit internalFormat GL_RGBA http.download.nvidia.com/developer/Papers/2005/…
KindDragon
Ich würde es unterlassen, den internalFormat-Parameter als "Bildformat" umzubenennen, da dies ebenso verwirrend ist. Vielleicht ist es sinnvoll, sich "internalFormat" als "Texturpixelformat" vorzustellen. Die Parameterkombination "Format" und "Typ" ist das "Quellpixelformat" (das oft ein Bild ist, daher mein Kommentar). Und dann gibt es natürlich das GPU-Format, das BGRA für ganzzahlige Formate ist.
StarShine
6

Im Allgemeinen unterstützt die meiste Hardware keine 3-Komponenten-Texturformate. In diesem Beispiel können Sie also davon ausgehen, dass sie konvertiert wurde. Eine 3-Komponenten-OpenGL-Textur besteht in der Hardware aus 4 Komponenten, wobei die Alpha-Komponente ignoriert / auf 255 / was auch immer gesetzt wird.

https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (Diese Seite "Häufige Fehler" ist eine Goldmine - bookmarken Sie sie jetzt!)

Für einen allgemeineren Fall kann die Leistung von glTexSubImage2D einen guten Hinweis darauf geben, ob der Upload einen Softwarekonvertierungspfad durchlaufen muss oder nicht. Sie würden dies während des Programmstarts tun - erstellen Sie einfach eine leere Textur (über glTexImage2D mit NULL-Daten) und geben Sie dann eine Reihe von glTexSubImage2D-Aufrufen aus, denen jeweils ein glFinish folgt, um sicherzustellen, dass der Vorgang abgeschlossen ist. Ignorieren Sie den ersten, da dafür Caches / States / etc eingerichtet werden, und planen Sie den Rest. Wiederholen Sie diesen Vorgang für einige verschiedene Formate und wählen Sie das schnellste aus.

Eine andere Alternative - da Sie diese Frage mit "Windows" markiert haben - besteht darin, beim Start ein D3D-Gerät zu erstellen (direkt nachdem Sie Ihr Fenster erstellt haben, aber bevor Sie OpenGL starten) und dann mit D3D nach Formatunterstützung zu suchen. Während OpenGL die Konvertierung von Software in ein gültiges internes Format ermöglicht, ist dies bei D3D nicht der Fall - wenn es nicht von der Hardware unterstützt wird, können Sie dies nicht tun. Dann zerstöre D3D und rufe OpenGL auf. (Diese Technik kann auch zum Abfragen anderer Dinge verwendet werden, die OpenGL nicht direkt abfragen lässt.)

Es ist eine nützliche Faustregel, um zu überprüfen, was Sie in OpenGL mit der D3D-Dokumentation tun. Wenn D3D etwas nicht kann, kann dies ein guter Hinweis darauf sein, dass das betreffende Objekt in der Hardware nicht unterstützt wird. Nicht immer wahr, aber ein nützlicher Ausgangspunkt.

Maximus Minimus
quelle