OpenGL 纹理不适用于大于 1x1 的分辨率

Posted

技术标签:

【中文标题】OpenGL 纹理不适用于大于 1x1 的分辨率【英文标题】:OpenGL texture does not work with resolutions greater than 1x1 【发布时间】:2017-10-13 16:04:35 【问题描述】:

我目前正在为我正在开发的 3D 游戏开发 GUI 系统。我正在使用实例渲染来很好地平衡速度和内存使用情况。到目前为止一切正常,我能够在屏幕上显示多个彩色矩形(最高 200k@60fps)。

现在,我正在尝试添加纹理以显示字符、图标和帧缓冲区内容。这就是我的问题发生的地方。我使用 FreeImage 作为图像加载库。加载图像文件并创建 OpenGL 纹理对象的代码直接从另一个项目复制而来。

当我尝试显示纹理时,我只在屏幕上看到一个黑色矩形。请注意,代码在旧项目中运行良好。我看到一个彩色框的唯一情况是,当我将 and 高度传递给glTexImage2D 设置为1 时:

glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)bits)

除此之外的一切都不起作用。 glGetError() 没有生成错误代码。我也尝试过生成随机纹理,但大小超过 1x1 的纹理都不起作用:

float* data = new float[4 * 2 * 2 * 4]
    1.0f,0.3f,0.5f,1.0f,
    0.0f,0.7f,0.5f,1.0f,
    0.0f,0.5f,0.2f,1.0f,
    0.0f,0.0f,0.0f,1.0f
;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0, GL_RGBA, GL_FLOAT, (void*)data);

我将 GLFW 用于窗口,并使用 GLEW 来启用现代 OpenGL。我的 IDE 是 VS2017,我正在为我的 GTX1060(GL 4.6.0、387.92)运行带有最新 nVidia 驱动程序的 Windows 10 64 位。由于最近几天我一直在寻找我的错误,因此如果有人可以提供帮助会很好。

完整的纹理加载代码可用here。如果需要更多信息或代码,请发表评论。

【问题讨论】:

编辑minimal reproducible example。 不知道是不是例子的问题。它是最小的,因为显示了产生问题的三行,并且它们周围的一切都无关紧要。它是完整的,因为问题出现在示例中,并且由于我两天前开始调试以来代码对我不起作用,因此我无法验证。 @Professor901 通常,MCVE 源代码的标准要求是使人们能够 1) 将代码复制并粘贴到文件中 2) 使用 oneliner 编译它(由你)3)执行和测试程序。你提供的链接是ok 【参考方案1】:

我发现这里有两个问题

FreeImage_GetBits() 函数将返回指向以 FreeImage 内部格式存储的数据的指针。其中每条扫描线通常与 4 字节边界对齐。当您拥有二次幂纹理时,这将正常工作。但是,对于 NPOT 纹理,您需要为 OpenGL 指定正确的解包对齐方式。

使用可以使用以下功能

FreeImage_ConvertToRawBits() 返回非对齐位,适用于 NPOT 纹理。

第二个问题可能是没有为 mipmap 指定过滤模式 尝试在调用 glTexImage2D() 后添加以下行

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

还有一个你正在使用内部格式,它是第三个参数作为 GL_RGBA,所以你告诉 opengl 将像素数据解释为 RGBA,但是你将第 7 个参数作为 GL_BGRA,所以你告诉我在像素数组中给出的数据是对齐线 BGRA 这真的是你的意思吗? 也检查一下。

【讨论】:

澄清一下,第二个问题是纹理“不完整”。使用 GL_LINEAR 会使其完整,但生成 mipmap 也会使其完整。 第二个是它。谢谢【参考方案2】:

如果创建大小为 2000x1000 的纹理后,glGetError() 返回 0,则问题可能出在您的渲染代码上。 您也可以通过

检查纹理的纹理大小
int w=0;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); 

尽管并非所有地方都支持它。

【讨论】:

以上是关于OpenGL 纹理不适用于大于 1x1 的分辨率的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL代码适用于GLFW,但不适用于Qt OpenGL

Android OpenGL camera2 纹理分辨率

Android OpenGL camera2纹理分辨率

OpenGL:如何渲染完美的矩形渐变?

Opengl Array Texture,适用于原始数据,但不适用于图像数据

Opengl 纹理映射和图像分辨率