在glGenTextures / glBindTexture之后破坏纹理编号OpenGL

时间:2013-09-05 16:59:00

标签: c++ opengl opengl-es

我在OpenGL上的一个纹理有一个可怕的行为。

删除纹理后,我创建一个新纹理,它生成与以前相同的tex编号,但纹理不正确。 glGetError也会在每一行返回0!我尝试在glDeleteTextures之后添加glFlush / glFinish,但它没有改变任何东西!纹理编号似乎锁定在某处......为什么?

它是单线程的,这里是行为:

//myTexture == 24 is loaded and works correctly
GLboolean bIsTexture = glIsTexture(myTexture); //returns 1 = > ok
glDeleteTextures(1,&myTexture);
bIsTexture = glIsTexture(myTexture); //returns 0 => ok

//Let's create a new texture
glGenTextures(1,&myTexture);//myTexture == 24 (as the glDelete was ok)
glBindTexture(GL_TEXTURE_2D,myTexture);     
bIsTexture = glIsTexture(myTexture); //returns 0 => FAILS

3 个答案:

答案 0 :(得分:6)

在创建纹理之前调用BindTexture为0:

//Let's create a new texture
glBindTexture(GL_TEXTURE_2D,0); // free the old bind texture if deleted
glGenTextures(1,&myTexture);//myTexture == 24 (as the glDelete was ok)
glBindTexture(GL_TEXTURE_2D,myTexture);     
bIsTexture = glIsTexture(myTexture); //returns 1 => Ok

答案 1 :(得分:2)

嗯,你在创建新纹理的常用操作序列中缺少一个重要步骤:实际上是分配它。

//Let's create a new texture

glGenTextures(1,&myTexture);//myTexture == 24 (as the glDelete was ok)
glBindTexture(GL_TEXTURE_2D,myTexture);     

在这里你必须调用glTexImage2D或glTexStorage来实际分配纹理对象。在这样做之前,没有与生成的纹理名称相关联的纹理数据。这很重要:glGenTextures生成的值不是纹理,而是纹理名称(即句柄),而OpenGL声明这应该是纹理对象,一个有缺陷的司机可能会错误地解释它。

glTexImage2D(…); // <<<<<
bIsTexture = glIsTexture(myTexture); //returns …

更新

正如Andon M. Coleman指出的那样(感谢你),将纹理名称绑定到纹理目标会产生纹理对象(与所述名称相关联)。因此,在这种情况下,应该期望glIsTexture返回GL_TRUE。现在,这就是现实与理想的规范世界的不同之处:实际(错误)驱动程序可能被错误地实现,并且只有在存在实际数据存储时才假设名称与纹理对象相关联,因此可能需要进行实际操作。分配看效果。

实际上,通常在名称分配后很快就会进行存储分配。我认为测试套件中使用的驱动程序的实现者没有检查这个角落情况。编写错误报告的时间。

答案 2 :(得分:2)

glIsTexture (...)唯一能做的就是让你知道OpenGL名称(句柄)是否属于纹理。实际上,OpenGL名称在首次使用之前并未实际与其最终目的相关联。在纹理名称的情况下,glIsTexture仅检查名称是否与纹理相关联;第一次使用名称调用glBindTexture (...)时会发生此关联。 glIsTexture 告诉您该名称是否具有相关数据存储(例如您调用glTexImage2D (...)或OpenGL 4+ glTexStorage (...))。

这是一个有趣的琐事:在OpenGL 3.0之前,规范。允许你为对象名称提出任何未使用的数字,OpenGL会像处理glGen___ (...)函数来生成名称一样对待它;这可以仍然在兼容性配置文件中完成。这就是名称生成功能在宏观计划中的重要性。

这里最重要的是,名字在拳头使用时被赋予了它们的功能。更重要的是glIs___ (...)只是告诉你名称是否与特定类型的OpenGL对象相关联(而不是它是一个有效/初始化的/ ...对象)。


我刚才提到的官方解释来自OpenGL规范,其中规定:

  

命令:

     

void GenTextures( sizei n, uint *textures );

     

在纹理中返回先前未使用的纹理名称。这些名称仅标记为已使用,仅用于GenTextures,但它们仅在第一次绑定时获取纹理状态和维度,就像它们未被使用一样。

     

通过调用:

实现绑定      

void BindTexture( enum target, uint texture );

     

将目标设置为所需的纹理目标,并将纹理设置为未使用的名称。生成的纹理对象是一个新的状态向量,包含8.21节中列出的所有状态和相同的初始值。绑定到目标的新纹理对象是,并且仍然是目标指定的维度和类型的纹理,直到它被删除。



由于这是所有 glIsTexture (...)应该做的,我不得不假设这是一个驱动程序错误。