Answers:
您的问题似乎混淆了某些概念,因此让我们从头开始。这是函数的定义glTexImage2D
:
void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data );
您可能将两件事称为“纹理格式”。第一个是internalformat
参数。这是OpenGL存储图像的真实 格式。该format
参数描述了像素数据的格式的一部分,你与提供data
参数。
为了把它的另一种方式,format
并type
定义什么你的数据的模样。internalformat
这就是告诉OpenGL 存储数据的方式。让我们把format
与type
该“像素传输格式”,而internalformat
将是“图像格式”。
纹理的图像格式永远不能为“ bgr8”。没有GL_BGR8图像格式枚举器。这里是一个GL_BGR枚举,但这是像素传输格式,而不是图像格式。
换句话说,给OpenGL的像素数据可以按BGR顺序存储。但是OpenGL实现自行决定如何实际存储该像素数据。也许它以小端顺序存储。也许它存储大端。也许只是随意重新排列字节。您不知道,并且OpenGL没有提供一种查找方法。
无法判断一组特定的像素传输格式参数是否与给定图像格式的OpenGL实现如何存储它们匹配。
现在有一种说法。“现在”是指OpenGL 4.3和/或ARB_internalformat_query2。来到您附近的显卡:
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
而type
现在有实现的首选format
,并type
使用glTex(Sub)Image
到调用GL_RGBA8
图像。有独立format
和type
查询的glReadPixels
下载。
有可以使其他查询。
如果您无权访问这些文件,则可以使用大多数硬件将遵循的一些一般经验法则:
GL_BGRA
的format
,和GL_UNSIGNED_INT_8888
或GL_UNSIGNED_BYTE
为type
。GL_BGRA
format
与GL_RGB8
图像格式,即使你必须把虚拟数据的alpha分量。通常,大多数硬件不支持3分量纹理格式,因此在此特定示例中,您可以合理地假设它已转换。3分量OpenGL纹理实际上是硬件中的4分量,但是alpha分量被忽略/设置为255 /任何。
https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (该“常见错误”页面是金矿-现在将其添加为书签!)
对于更一般的情况,glTexSubImage2D性能可以很好地指示上载是否必须通过软件转换路径。您将在程序启动期间进行此操作-只需创建一个空纹理(通过具有NULL数据的glTexImage2D),然后发出一堆glTexSubImage2D调用,每个调用之后都要执行一次glFinish以确保其完成。忽略第一个,因为正在为其设置缓存/状态/等,并为其余时间计时。对几种不同的格式重复此操作,然后选择最快的格式。
另一个选择-就像您已将此问题标记为“ Windows”一样,是在启动时创建D3D设备(就在创建窗口之后,但在初始化OpenGL之前),然后使用D3D检查格式支持。尽管OpenGL允许将软件转换为有效的内部格式,但D3D不允许-如果硬件不支持它,则不能这样做。然后销毁D3D并启动OpenGL。(此技术还可用于查询OpenGL不允许您直接查询的其他内容)。
实际上,使用D3D文档来交叉检查您在OpenGL中的操作是一条有用的经验法则。如果D3D无法执行某项操作,则可以很好地表明硬件中不支持某些问题。并非总是如此,而是一个有用的起点。