glGenTextures返回现有纹理名称

时间:2013-06-20 18:24:56

标签: ios objective-c opengl-es textures

我使用的是iOS 6.1.4,OpenGL ES 2,并且遇到奇怪的行为,glGenTextures返回纹理“名称”,之前已由glGenTextures返回。

具体来说,在初始化时,我遍历我的纹理并让OpenGL知道它们,如下所示:

// Generate the OpenGL texture objects
for (Object3D *object3D in self.objects3D)
{
    [self installIntoOpenGLObject3D:object3D];
}

- (void)installIntoOpenGLObject3D:(Object3D *)object3D
{
    GLuint nID;
    glGenTextures(1, &nID);

    Texture *texture = object3D.texture;
    texture.identifier = nID;
    glBindTexture(GL_TEXTURE_2D, nID);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, [texture width], [texture height], 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)[texture pngData]);
    ARLogInfo(@"Installed texture '%@' with OpenGL identifier %d", texture.name, texture.identifier);
}

目前,我看到了1, 2, 3, ... n之类的纹理名称。

但是,稍后(异步网络调用返回后)我创建新纹理并调用installIntoOpenGLObject3D:来安装它们。正是在这个时候,我看到glGenTextures返回先前发出的名字。显然这会导致应用程序呈现不正确的纹理。

文档http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenTextures.xml表明:

  

调用glGenTextures返回的纹理名称不会被后续调用返回,除非它们首先使用glDeleteTextures删除。

我没有打电话给glDeleteTextures;然而,文档也说:

  

保证在调用glGenTextures之前不会立即使用返回的名称。

这令人困惑,因为它暗示如果返回的名称不是“正在使用”,则返回的名称可能相同。据我所知,通过调用glBindTexture纹理满足“使用中”的概念,但是,有些事情是错误的。

我的另一个想法可能是EAGLContext在第一组glGenTextures调用之间发生了变化,但是,唉,在调试器中单步调试告诉我上下文没有改变。

作为一种(也许是愚蠢的)hackish解决方法,我试图确保纹理名称本身就是独一无二的,如下所示,但是我最终得到的是一个我不跟踪的纹理名称,但仍然代表了不同的纹理,所以这种方法没有提供解决方法:

- (void)installIntoOpenGLObject3D:(Object3D *)object3D
{
    if (!self.object3DTextureIdentifiers)
    {
        self.object3DTextureIdentifiers = [NSMutableSet set];
    }

    GLuint nID;
    NSNumber *idObj;
    do {
        glGenTextures(1, &nID);
        GLboolean isTexture = glIsTexture(nID);
        idObj = [NSNumber numberWithUnsignedInt:nID];
    } while ([self.object3DTextureIdentifiers containsObject:idObj]);

    [self.object3DTextureIdentifiers addObject:idObj];

    Texture *texture = object3D.texture;
    texture.identifier = nID;
    glBindTexture(GL_TEXTURE_2D, nID);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, [texture width], [texture height], 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)[texture pngData]);
    ARLogInfo(@"Installed texture '%@' with OpenGL identifier %d", texture.name, texture.identifier);
}

关于为什么glGenTextures返回之前返回的名字的任何想法?

1 个答案:

答案 0 :(得分:3)

经过大量调试后,我认为是线程的根本原因。

虽然我确定glGenTextures只是从一个线程(main)调用,但事实证明,在其他线程上调用了对其他OpenGL方法的调用。重构所以对glGenTextures的调用也只发生在其他线程(not-main)上似乎解决了这个问题。