Votre question semble brouiller certains concepts, alors prenons les choses par le haut. Voici la définition de la fonction glTexImage2D
:
void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data );
Il y a deux choses que vous pourriez appeler des "formats de texture". Le premier est le internalformat
paramètre. Il s'agit du véritable format de l'image telle qu'OpenGL la stocke. Le format
paramètre décrit une partie du format des données de pixels que vous fournissez avec le data
paramètre.
Pour le dire autrement format
et type
définir à quoi ressemblent vos données. internalformat
est la façon dont vous dites à OpenGL de stocker vos données. Appelons format
et type
le "format de transfert de pixels", tandis que internalformat
sera le "format d'image".
Le format d'image d'une texture ne peut jamais être "bgr8". Il n'y a pas d'énumérateur de format d'image GL_BGR8. Il y a une énumération GL_BGR, mais c'est pour le format de transfert de pixels, pas le format d'image.
Ou pour le dire autrement, vos données de pixels que vous donnez à OpenGL peuvent être stockées dans l'ordre BGR. Mais la mise en œuvre d'OpenGL décide seule de la façon de stocker réellement ces données de pixels. Peut-être qu'il le stocke dans un ordre peu endian. Peut-être qu'il le stocke en big-endian. Peut-être qu'il réorganise simplement arbitrairement les octets. Vous ne savez pas, et OpenGL ne fournit aucun moyen de le savoir.
Il n'y a aucun moyen de savoir si un ensemble particulier de paramètres de format de transfert de pixels correspond à la façon dont l'implémentation OpenGL les stockera compte tenu du format d'image.
Il y a un moyen de le dire maintenant. Et par "maintenant", je veux dire dans OpenGL 4.3 et / ou ARB_internalformat_query2. Venir sur une carte graphique près de chez vous:
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);
format
et type
ont maintenant l'implémentation préférée format
et type
pour utiliser les glTex(Sub)Image
appels aux GL_RGBA8
images. Il sont séparés format
et les type
requêtes pour les glReadPixels
téléchargements.
Il existe d' autres requêtes que vous pouvez effectuer .
Si vous n'y avez pas accès, vous pouvez utiliser certaines règles générales que la plupart des matériels respecteront:
- stockera les données de pixels pour les données de 8 bits par canal dans l'ordre BGRA. Donc, si vous souhaitez faire correspondre le format avec vos données de pixels, afin de télécharger plus rapidement les données de texture, vous souhaitez utiliser
GL_BGRA
pour le format
et GL_UNSIGNED_INT_8888
ou GL_UNSIGNED_BYTE
pour le type
.
- ne stockera pas réellement les couleurs 24 bits en 24 bits. Il les remplira toujours en 32 bits; l'alpha sera simplement ignoré lors de la lecture des données. Donc , si vous voulez faire correspondre les formats, utilisez toujours
GL_BGRA
format
avec les GL_RGB8
formats d'image, même si vous devez mettre des données fictives dans le composant alpha.
Généralement, la plupart des matériels ne prennent pas en charge les formats de texture à 3 composants, donc dans cet exemple spécifique, vous pouvez faire une supposition raisonnablement sûre qu'il est converti. Une texture OpenGL à 3 composants est en fait à 4 composants dans le matériel, mais avec le composant alpha ignoré / défini sur 255 / peu importe.
https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (Cette page "erreurs courantes" est une mine d'or - ajoutez-la à vos favoris maintenant!)
Pour un cas plus général, les performances de glTexSubImage2D peuvent vous donner une bonne indication si le téléchargement doit ou non passer par un chemin de conversion logicielle. Vous iriez à ce sujet au démarrage du programme - créez simplement une texture vide (via glTexImage2D avec des données NULL), puis émettez un tas d'appels glTexSubImage2D, chacun suivi d'un glFinish pour vous assurer qu'il se termine. Ignorez le premier car des caches / états / etc sont en cours de configuration pour lui, et chronométrez les autres. Répétez cette opération pour quelques formats différents et choisissez le plus rapide.
Une autre alternative - vu que vous avez marqué cette question "Windows" - consiste à créer un périphérique D3D au démarrage (juste après avoir créé votre fenêtre mais avant de lancer OpenGL), puis utilisez D3D pour vérifier la prise en charge du format. Alors qu'OpenGL permet la conversion logicielle dans un format interne valide, D3D ne le fait pas - s'il n'est pas pris en charge par le matériel, vous ne pouvez pas le faire. Détruisez ensuite D3D et ouvrez OpenGL. (Cette technique peut également être utilisée pour interroger d'autres éléments qu'OpenGL ne vous permet pas d'interroger directement).
C'est en fait une règle d'or utile pour vérifier ce que vous faites dans OpenGL avec la documentation D3D. Si D3D ne peut pas faire quelque chose, cela peut être une bonne indication que le quelque chose en question n'est pas pris en charge par le matériel. Pas toujours vrai, mais un point de départ utile.
la source