5

私は 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ですが、残念ながら、デバッガーをステップ実行すると、コンテキストが変更されていないことがわかりました。

(おそらくばかげた) ハック的な回避策として、以下に示すように、テクスチャ名が一意であることを確認しようとしましたが、追跡していないテクスチャ名になってしまい、別のテクスチャを表しているため、これはアプローチは回避策を提供しません:

- (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以前に返された名前を返す理由について何か考えはありますか?

4

1 に答える 1

3

多くのデバッグを行った結果、根本的な原因はスレッド化にあると考えています。

1 つのスレッド (メイン) からのみ呼び出されていることは確かglGenTexturesでしたが、他の OpenGL メソッドへの呼び出しが別のスレッドで呼び出されていたことが判明しました。glGenTexturesへの呼び出しが他のスレッド (メインではない) でのみ発生するようにリファクタリングすると、問題が解決されるようです。

于 2013-06-25T20:46:43.543 に答える