1

我在 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
4

3 回答 3

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
于 2013-09-06T07:48:44.053 回答
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 。现在,现实与理想的规范世界有什么不同:实际的(有缺陷的)驱动程序可能被错误地实现,并且仅在存在实际数据存储时才假定名称与纹理对象相关联,因此可能有必要进行实际操作分配看看效果。

实际上,您通常在名称分配后很快就进行存储分配。我假设您的驱动程序的实现者使用的测试套件不会检查这种极端情况。是时候写一个错误报告了。

于 2013-09-05T17:14:57.133 回答
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 );

在纹理中返回 n 个以前未使用的纹理名称。这些名称被标记为已使用,仅出于 GenTextures 的目的,但它们仅在首次绑定时才获得纹理状态和维度,就像它们未使用一样。

绑定通过调用实现:

void BindTexture( enum target, uint texture );

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



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

于 2013-09-05T17:29:48.937 回答