简单的OpenGL纹理映射无法工作?

8

我正在尝试在OpenGL中了解纹理映射,但我无法使一个简单的示例正常工作。

虽然多边形被绘制出来了,但它只是一个纯色而没有纹理。同时,位图正确地加载到sprite1[]中,因为我一直成功使用glDrawPixels到现在为止。

我使用glGenTextures来获取我的纹理名称,但我注意到它不会改变texName1;即使在调用glGenTextures之后,这个GLuint仍然是我初始化它时的值...

我已启用GL_TEXTURE_2D。

以下是代码:

GLuint texName1 = 0;

glGenTextures(1, &texName1);
glBindTexture(GL_TEXTURE_2D, texName1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, sprite1[18], sprite1[22], 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &sprite1[54]);

glColor3f(1, 1, 0);
glBindTexture(GL_TEXTURE_2D, texName1);
glBegin(GL_QUADS);
    glTexCoord2f (0.0, 0.0);
    glVertex3f (0.0, 0.0, -5.0f);
    glTexCoord2f (1.0, 0.0);
    glVertex3f (.5, 0.0, -5.0f);
    glTexCoord2f (1.0, 1.0);
    glVertex3f (.5, .5, -5.0f);
    glTexCoord2f (0.0, 1.0);
    glVertex3f (0.0, .5, -5.0f);
glEnd();

更新: 我很困惑。这是我尝试过的所有方法:

  1. 结果发现在OGL初始化之前就初始化了纹理。纹理是在类构造函数中初始化(glGenTextures->glTexImage2D),并且在每帧调用的成员函数中绘制(glBegin->glEnd)。genTextures现在似乎正常工作,我得到了名称为1的纹理。

  2. 尝试了所有可能的GL_RGBA8、GL_BGRA_EXT(GL_BGRA在我的系统上不起作用;我需要使用_EXT)、甚至从位图中删除了alpha通道,并尝试了所有GL_RGB、GL_BGR_EXT等等的组合。没有成功。

  3. 尝试了程序创建位图并使用它

  4. 确保GL_COLOR_MATERIAL未启用。

  5. 将位图大小更改为32x32。

  6. 尝试使用glTexEnvi而不是glTexEnvf。


1
如果在glGenTextures之后texName1仍为0,您应该检查错误条件... - Jason Coco
sprite1[] 中的宽度和高度是以 byte 还是 int 存储的? - Maurice Gilden
1
宽度和高度以字节小端存储。我之前已经成功使用过sprite1 [18]和sprite1 [22]与glDrawPixels; 它们是正确的。位图只有29x20像素,所以可以工作。 - Tony R
2
另外,我该如何检查错误条件?从参考页面上看不出glGenTextures生成任何对我有用的错误,可以使用glGetError()。 - Tony R
7个回答

7
除了mentat的注意事项,你提到可能存在非二次幂纹理尺寸的问题,并且你还提到了纹理名称生成未能改变名称的情况。
这听起来好像是你在OpenGL初始化之前就调用了glGenTextures()。如果不是这个原因,我建议在调用glGenTextures()后添加代码以检查OpenGL错误状态,方法是调用glGetError()

这对我有用... 我之前尝试在OpenGL初始化之前创建纹理。正如我一次又一次看到的那样:函数调用的顺序在OpenGL编程中非常重要。 - chembrad

4

在您的评论中,您提到您的位图大小为29x20像素。据我所知,为了生成有效的纹理,OpenGL要求图像尺寸(每个维度上)是2的幂次方。它不需要是正方形,但可以是矩形。您可以通过使用一些OpenGL扩展,例如GL_ARB_texture_rectangle来克服这个问题。


1
自OpenGL 2.0起,GL_ARB_texture_rectangle已被纳入OpenGL中。http://www.opengl.org/wiki/NPOT_Texture - Kos

2

我把这个放在这里是因为我遇到了同样的问题,并找到了另一篇文章解释了这个问题。 iPhone确实支持GL_BGRA(GL_EXT_BGRA),但似乎只作为输入格式而不是内部格式。因此,如果您将glTexImage2D调用更改为具有GL_RGBA内部格式,则可以解决此问题。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, &sprite1[54]);

我希望这篇文章能帮助到其他遇到同样问题的人。

我很想听更多关于这个问题的解释,因为它一直让我感到困惑。似乎将BGRA作为内部格式使用是可行的,但实际上它使用的是RGBA。或者我错了吗? - akaru

1

我的OpenGL有点生疏,但我记得在使用glTexImage2D时遇到了同样的问题。最终我设法让它工作了,但我总是更喜欢使用gluBuild2DMipmaps,所以我最终选择了它。

gluBuild2DMipmaps (
  GL_TEXTURE_2D, type, i.width, i.height, type, GL_UNSIGNED_BYTE, i.data
);

被替换的

glTexImage2D (
  GL_TEXTURE_2D, 0, type, i.width, i.height, 0, type, GL_UNSIGNED_BYTE, i.data 
);

1
这听起来像是MIN过滤器的一个被遗忘的glTexParameter。默认值应该是GL_NEAREST_MIPMAP_LINEAR,只适用于使用mipmapped纹理的情况。 - Maurice Gilden

1

一些随机的想法:

  • GL_COLOR_MATERIAL 可能已启用
  • 将 "glTexEnvf" 更改为 "glTexEnvi",看看是否有帮助
  • 如果 glGenTextures 后 texName1 为 0,则可能没有活动的 OpenGL 上下文

对于错误检查,我建议编写一个小函数,打印 glGetErrors 的最常见结果的可读输出,并使用它来查找创建错误的行。另一个可能性是使用类似 GLIntercept, BuGLegDEBugger 的工具。


1
我找到了问题所在。我的调用glEnableglEnable(GL_BLEND | GL_TEXTURE_2D)。使用glGetError,我发现这个调用返回了GL_INVALID_ENUM,所以我将GL_TEXTURE_2D移动到它自己的启用函数中,然后就解决了。我猜逻辑或不允许在glEnable中使用?

1
据我所知,OpenGL常量不仅仅是2的幂次方,它们是任意值。这意味着使用逻辑或运算符会破坏信息。 - Adam
1
可进行OR运算的常量是名称中带有-BIT的常量,例如GL_COLOR_BUFFER_BIT。在GL中并不多见,所以不要过于依赖它们。 - Kos

0

首先,我会检查颜色材质设置,就像ShadowIce提到的那样,然后检查你的纹理文件,确保它是一个合理的大小(比如256x256),并且是一个RGB位图。如果文件有任何问题,无论你如何尝试,它都不会正确渲染。

然后,我会停止尝试仅仅调试那段代码,而是看看你与NeHe网站上的教程有什么不同。

如果你想在OpenGL中做一些事情,NeHe总是一个好地方去查找。纹理可能是最难搞定的东西,而且随着你的GL技能的增加,它们只会变得更加困难。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接