Come rilevare quali formati di texture OpenGL sono supportati in modo nativo?


10

Ad esempio, come rilevare se la mia videocard non supporta "bgr8" e convertirlo in un altro formato, come "rgba8" in modalità software.

AGGIORNAMENTO: scusate la confusione. Questa domanda riguarda la situazione quando imposto internalFormat in glTexImage2D su qualcosa come "bgra8" ma il videodriver converte internamente i dati in un altro formato, come "rgba8".

Risposte:


11

La tua domanda sembra confondere alcuni concetti, quindi prendiamo le cose dall'alto. Questa è la definizione della funzione glTexImage2D:

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

Ci sono due cose che potresti chiamare "formati di trama". Il primo è il internalformatparametro. Questo è il vero formato dell'immagine mentre OpenGL la memorizza. Il formatparametro descrive parte del formato dei dati pixel forniti con il dataparametro.

Per dirla in un altro modo formate typedefinire l' aspetto dei dati. internalformatè come stai dicendo a OpenGL di archiviare i tuoi dati. Chiamiamo formate typeil "formato di trasferimento pixel", mentre internalformatsarà il "formato immagine".

Il formato dell'immagine di una trama non può mai essere "bgr8". Non esiste un enumeratore del formato immagine GL_BGR8. V'è un enum GL_BGR, ma che è per il formato di trasferimento dei pixel, non il formato di immagine.

O, per dirla in altro modo, i dati dei pixel forniti a OpenGL possono essere archiviati in ordine BGR. Ma l'implementazione OpenGL decide autonomamente come archiviare effettivamente quei dati pixel. Forse lo memorizza in ordine little-endian. Forse lo memorizza big-endian. Forse riorganizza arbitrariamente i byte. Non lo sai e OpenGL non fornisce un modo per scoprirlo.

Non è possibile stabilire se un determinato set di parametri del formato di trasferimento dei pixel corrisponda al modo in cui l'implementazione OpenGL li memorizzerà in base al formato dell'immagine.

C'è un modo per dirlo ora. E per "ora" intendo in OpenGL 4.3 e / o ARB_internalformat_query2. Venendo a una scheda grafica vicino a te:

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);

formate typeora hanno l'implementazione preferita formate typeper l'utilizzo di glTex(Sub)Imagechiamate alle GL_RGBA8immagini. Ci sono separati formate typequery per i glReadPixelsdownload.

Ci sono altre domande che puoi fare .

Se non hai accesso a questi, puoi utilizzare alcune regole generali a cui la maggior parte dell'hardware aderirà:

  • memorizzerà i dati pixel per i dati a 8 bit per canale nell'ordine BGRA. Quindi, se si desidera abbinare il formato con i dati dei pixel, in modo da caricare più rapidamente i dati delle trame, si desidera utilizzare GL_BGRAper format, e GL_UNSIGNED_INT_8888o GL_UNSIGNED_BYTEper type.
  • in realtà non memorizzerà i colori a 24 bit come 24 bit. Li riempirà sempre a 32 bit; l'alfa verrà semplicemente ignorato quando legge i dati. Quindi, se si desidera abbinare i formati, utilizzare sempre GL_BGRA formatcon i GL_RGB8formati di immagine, anche se è necessario inserire dati fittizi nel componente alfa.

4
Ho trovato anche meglio usare il formato GL_BGRA con internalFormat GL_RGBA http.download.nvidia.com/developer/Papers/2005/…
KindDragon

Vorrei trattenermi dal rebranding del parametro internalFormat come "formato immagine", perché è altrettanto confuso. Forse ha senso pensare a "internalFormat" come al "formato pixel texture". La combinazione di parametri "formato" e "tipo" sono il "formato pixel sorgente" (che spesso è un'immagine, quindi il mio commento). E poi ovviamente c'è il formato GPU, che è BGRA per i formati di tipo intero.
StarShine

6

Generalmente la maggior parte dell'hardware non supporta i formati di trama a 3 componenti, quindi in questo esempio specifico è possibile supporre che sia convertito in modo ragionevolmente sicuro. Una trama OpenGL a 3 componenti è in realtà a 4 componenti nell'hardware ma con il componente alfa ignorato / impostato su 255 / qualunque cosa.

https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (Quella pagina "errori comuni" è una miniera d'oro - aggiungilo ai segnalibri adesso!)

Per un caso più generale, le prestazioni di glTexSubImage2D possono darti una buona indicazione se il caricamento deve o meno passare attraverso un percorso di conversione del software. Avresti fatto questo durante l'avvio del programma - basta creare una trama vuota (tramite glTexImage2D con dati NULL), quindi emettere un gruppo di chiamate glTexSubImage2D, ciascuna seguita da una glFinish per assicurarsi che venga completata. Ignora il primo perché le cache / stati / ecc. Sono in fase di configurazione e cronometra il resto. Ripeti l'operazione per alcuni formati diversi e scegli quello più veloce.

Un'altra alternativa - visto che hai taggato questa domanda "Windows" - è quella di creare un dispositivo D3D all'avvio (subito dopo aver creato la tua finestra ma prima di avviare OpenGL) quindi utilizzare D3D per verificare il supporto del formato. Mentre OpenGL consente la conversione del software in un formato interno valido, D3D no - se non è supportato dall'hardware non è possibile farlo. Quindi distruggi D3D e apri OpenGL. (Questa tecnica può anche essere usata per interrogare altre cose che OpenGL non ti consente di interrogare direttamente).

In realtà è un'utile regola empirica per eseguire un controllo incrociato di ciò che stai facendo in OpenGL con la documentazione D3D. Se D3D non può fare qualcosa, può essere una buona indicazione che qualcosa in questione non è supportato nell'hardware. Non sempre vero, ma un utile punto di partenza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.