【问题标题】:OpenGL textures: why does order matter?OpenGL 纹理:为什么顺序很重要?
【发布时间】:2012-03-09 12:20:39
【问题描述】:

我正在尝试设置一个简单的函数,这将使我更容易在 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 的新手。

下面是我正在谈论的白盒的屏幕截图:

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

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

【问题讨论】:

  • "auxDIBImageLoad" 请永远不要使用GLaux。如果需要图片加载,有many actually good libraries for it.
  • 我问这个的原因实际上主要是因为我在尝试加载纹理时得到了这个白框,我认为这可能与函数的顺序有关,但它看来并非如此。还有什么可能导致这个白框出现?
  • 我认为这与订单有关,因为如果我要删除if (!TextureImage[TextNum]),那么纹理会出现,但考虑到每次渲染帧时都会调用MapTexture(),没有if (!TextureImage[TextNum]),内存会像疯了一样泄漏,直到程序崩溃。

标签: c++ opengl texture-mapping


【解决方案1】:

是的,顺序绝对重要。

  • glGenTexture 创建纹理名称。

  • glBindTextureglGenTexture生成的纹理名称,所以不能在glGenTexture之前运行。

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

OpenGL 的客户端接口是一个 Big Giant Squggly 状态机。您可以更改大量的参数和标志,并且您必须谨慎地始终让 OpenGL 处于正确的状态。这通常意味着弹出您推送的矩阵并恢复您修改的标志(至少在 OpenGL 1.x 中)。

【讨论】:

    【解决方案2】:

    OpenGL 是一个状态机,这意味着您可以拉动它的控制杆,转动它的旋钮,它会保留这些设置,直到您主动更改它们。

    不过,它还管理对象中的持久数据。 这些对象是抽象的,不能与屏幕上看到的对象混淆! 现在在外部,OpenGL 通过它们所谓的 name(一个数字 ID)来识别对象。您创建了一个名称(列表)——但不是对象! – glGenTextures 用于纹理对象,这是一种 OpenGL 对象。

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

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


    否则,您的功能将指向正确的方向。 OpenGL 没有真正的初始化阶段,你只是随心所欲地做事。延迟加载数据直到您需要它是有意义的。但在实际绘制框架之前对对象列表进行多次迭代也是有意义的。其中一项准备工作应该是,您遍历所有对象(现在不是 OpenGL,而是您的)以测试数据是否已经加载。如果仍有大量数据丢失,请改为绘制加载屏幕,以免用户产生程序挂起的印象。甚至可能在单独的线程中执行冗长的加载操作,但对于 OpenGL,这需要一些预防措施。

    【讨论】:

      猜你喜欢
      • 2013-05-18
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 2018-02-01
      • 2017-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多