Su pregunta parece confundir ciertos conceptos, así que tomemos las cosas desde arriba. Esta es la definición de la función glTexImage2D
:
void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data );
Hay dos cosas que podría llamar "formatos de textura". El primero es el internalformat
parámetro. Este es el formato real de la imagen a medida que OpenGL la almacena. El format
parámetro describe parte del formato de los datos de píxeles que proporciona con el data
parámetro.
Para decirlo de otra manera, format
y type
definir cómo se ven sus datos. internalformat
así es como le estás diciendo a OpenGL que almacene tus datos. Llamemos format
y type
el "formato de transferencia de píxeles", mientras internalformat
que será el "formato de imagen".
El formato de imagen de una textura nunca puede ser "bgr8". No hay un enumerador de formato de imagen GL_BGR8. No es una enumeración GL_BGR, pero eso es para el formato de transferencia de píxeles, no el formato de imagen.
O para decirlo de otra manera, sus datos de píxeles que le da a OpenGL pueden almacenarse en orden BGR. Pero la implementación de OpenGL decide por sí misma cómo almacenar esos datos de píxeles. Tal vez lo almacena en orden little-endian. Tal vez lo almacena big-endian. Tal vez solo reorganiza arbitrariamente los bytes. No lo sabe, y OpenGL no proporciona una forma de averiguarlo.
No hay forma de saber si un conjunto particular de parámetros de formato de transferencia de píxeles coincide con cómo la implementación de OpenGL los almacenará dado el formato de imagen.
Hay una manera de saberlo ahora. Y por "ahora", quiero decir en OpenGL 4.3 y / o ARB_internalformat_query2. Llegando a una tarjeta gráfica cerca de usted:
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
y type
ahora tiene la implementación preferida format
y type
para usar glTex(Sub)Image
llamadas a GL_RGBA8
imágenes. Hay consultas separadas format
y type
para glReadPixels
descargas.
Hay otras consultas que puede hacer .
Si no tiene acceso a estos, puede usar algunas reglas generales a las que se adherirá la mayoría del hardware:
- almacenará datos de píxeles para datos de 8 bits por canal en orden BGRA. Por lo tanto, si desea hacer coincidir el formato con sus datos de píxeles, a fin de cargar más rápidamente los datos de textura, desea usarlos
GL_BGRA
para format
, GL_UNSIGNED_INT_8888
o GL_UNSIGNED_BYTE
para type
.
- en realidad no almacenará colores de 24 bits como 24 bits. Siempre los rellenará a 32 bits; el alfa solo será ignorado cuando lea los datos. Por lo tanto, si desea hacer coincidir formatos, use siempre
GL_BGRA
format
con GL_RGB8
formatos de imagen, incluso si tiene que poner datos ficticios en el componente alfa.
En general, la mayoría del hardware no admite formatos de textura de 3 componentes, por lo que en este ejemplo específico puede hacer una suposición razonablemente segura de que está convertido. Una textura OpenGL de 3 componentes es en realidad de 4 componentes en hardware pero con el componente alfa ignorado / configurado en 255 / lo que sea.
https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (Esa página de "errores comunes" es una mina de oro - ¡márquela ahora!)
Para un caso más general, el rendimiento de glTexSubImage2D puede darle una buena indicación de si la carga debe pasar por una ruta de conversión de software. Debería hacer esto durante el inicio del programa: simplemente cree una textura vacía (a través de glTexImage2D con datos NULOS), luego emita un montón de llamadas glTexSubImage2D, cada una seguida de un glFinish para asegurarse de que se complete. Ignora el primero porque se están configurando cachés / estados / etc. para ello, y cronometra el resto de ellos. Repita esto para algunos formatos diferentes y elija el más rápido.
Otra alternativa, ya que ha etiquetado esta pregunta como "Windows", es crear un dispositivo D3D al inicio (justo después de haber creado su ventana pero antes de iniciar OpenGL) y luego usar D3D para verificar la compatibilidad con el formato. Si bien OpenGL permite la conversión de software a un formato interno válido, D3D no lo hace; si el hardware no lo admite, no puede hacerlo. Luego destruya D3D y abra OpenGL. (Esta técnica también se puede utilizar para consultar otras cosas que OpenGL no le permite consultar directamente).
En realidad, es una regla práctica útil verificar lo que está haciendo en OpenGL con la documentación de D3D. Si D3D no puede hacer algo, puede ser una buena indicación de que el hardware en cuestión no es compatible. No siempre es cierto, pero es un punto de partida útil.
fuente