如何检测本机支持哪些OpenGL纹理格式?


10

例如,如何检测我的视频卡是否不支持“ bgr8”并将其转换为另一种格式,例如在软件模式下为“ rgba8”。

更新:很抱歉造成混乱。当我在glTexImage2D中将internalFormat设置为“ bgra8”之类的东西,但视频驱动程序在内部将数据转换为另一种格式(例如“ rgba8”)时,此问题更多地与情况有关。

Answers:


11

您的问题似乎混淆了某些概念,因此让我们从头开始。这是函数的定义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参数。

为了把它的另一种方式,formattype定义什么你的数据的模样。internalformat这就是告诉OpenGL 存储数据的方式。让我们把formattype该“像素传输格式”,而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);

formattype现在有实现的首选format,并type使用glTex(Sub)Image到调用GL_RGBA8图像。有独立formattype查询的glReadPixels下载。

可以使其他查询

如果您无权访问这些文件,则可以使用大多数硬件将遵循的一些一般经验法则:

  • 将以BGRA顺序存储每通道8位数据的像素数据。所以,如果你想以配合您的像素数据的格式,从而更快速上传纹理数据,你想用GL_BGRAformat,和GL_UNSIGNED_INT_8888GL_UNSIGNED_BYTEtype
  • 实际上不会将24位颜色存储为24位。它将始终将它们填充到32位。读取数据时,alpha只会被忽略。所以,如果你想匹配的格式,始终使用GL_BGRA formatGL_RGB8图像格式,即使你必须把虚拟数据的alpha分量。

4
我发现还更好地利用格式GL_BGRA与internalFormat GL_RGBA http.download.nvidia.com/developer/Papers/2005/...
KindDragon

我不会将internalFormat参数重命名为“图像格式”,因为它同样令人困惑。将“ internalFormat”视为“纹理像素格式”也许是有意义的。“格式”和“类型”参数组合是“源像素格式”(通常是图像,因此是我的评论)。当然还有GPU格式,对于整数类型格式是BGRA。
StarShine

6

通常,大多数硬件不支持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无法执行某项操作,则可以很好地表明硬件中不支持某些问题。并非总是如此,而是一个有用的起点。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.