OpenGL纹理:为什么订单很重要?

时间:2012-03-08 06:16:12

标签: c++ opengl texture-mapping

我正在尝试设置一个简单的函数,这将使我更容易在OpenGL中纹理地图几何体,但出于某种原因,当我试图制作一个天空盒时,我得到的是一个白色的盒子,而不是纹理映射几何。我认为有问题的代码包含在以下内容中:

void MapTexture (char *File, int TextNum) {
    if (!TextureImage[TextNum]){
        TextureImage[TextNum]=auxDIBImageLoad(File);
        glGenTextures(1, &texture[TextNum]);
        glBindTexture(GL_TEXTURE_2D, texture[TextNum]);
        glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[TextNum]->sizeX, TextureImage[TextNum]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[TextNum]->data);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    }
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[TextNum]);
//glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[TextNum]->sizeX, TextureImage[TextNum]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[TextNum]->data);
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

}

我不明白的一件大事是由于某种原因,glBindTexture()必须介于glGenTextures()glTexImage2D之间。如果我把它放在其他任何地方,它会搞砸一切。什么可能导致这个问题?对不起,如果它很简单,我对openGL来说是全新的。

下面是我正在谈论的白盒的截图: enter image description here

+++++++++++++++++++++++++++++++ 编辑 +++++++++++++++++++++++++++++++

在更多地使用代码之后,我意识到如果我在最后glTexImage2D()之后添加了glTexParameteri()glBindTexture(),那么所有纹理都会加载。为什么没有这两行会加载大多数纹理,但是有一些不会加载,为什么我必须为每一帧调用glTexImage(),但仅限于几个纹理?

2 个答案:

答案 0 :(得分:8)

是的,订单绝对重要。

  • glGenTexture创建纹理名称。

  • glBindTexture获取glGenTexture生成的纹理名称,因此无法在glGenTexture之前运行。

  • glTexImage2D将数据上传到当前绑定的纹理,因此无法在glBindTexture之前运行。

OpenGL的客户端界面是Big Giant Squggly State Machine。您可以更改大量的参数和标志,并且必须谨慎,始终将OpenGL保持在正确的状态。这通常意味着弹出矩阵,推送和恢复您修改的标志(至少在OpenGL 1.x中)。

答案 1 :(得分:4)

OpenGL是一个状态机,这意味着你可以拉动它的杠杆,转动它的旋钮,并保持这些设置,直到你主动更改它们。

然而,它还管理对象中的持久数据。 这些对象是抽象的东西,不能与屏幕上看到的对象混淆! 现在,OpenGL通过所谓的 name (一个数字ID)识别对象。您创建一个(列表)名称 - 但不是对象! - 使用glGenTextures作为纹理对象,这是一种OpenGL对象。

为了对这样的对象进行处理,必须首先将OpenGL置于一种状态,即以下所有调用该类型对象的调用都发生在一个特定对象上。这是通过glBindTexture完成的。在调用glBindTexture之后,所有以下调用操作纹理的调用都会发生在您刚刚绑定的那个纹理对象上。如果先前不存在该对象,则会在第一次绑定新的已分配对象名时创建该对象。 现在OpenGL使用该特定对象。

glTexImage2D只是用于处理当前绑定纹理数据的几个函数之一。


否则您的功能指向正确的方向。 OpenGL没有真正的初始化阶段,你只需要随身携带。在您需要之前推迟加载数据是有意义的。但是,在实际绘制帧之前,在对象列表上进行多次迭代也是有意义的。其中一个准备工作应该是迭代所有对象(现在不是OpenGL而是你的)来测试数据是否已经加载。如果仍然缺少大量数据,请改为绘制加载屏幕,这样用户就无法获得程序挂起的印象。甚至可能在单独的线程中执行冗长的加载操作,但是对于OpenGL,这需要一些预防措施。