iOS上的CVOpenGLESTextureCache vs glTexSubImage2D

时间:2012-10-10 06:42:07

标签: ios opengl-es textures

我的OpenGL应用程序使用OpenGL以全屏模式渲染纹理,并定期更新部分纹理。到目前为止,我一直在使用glTexImage2D来推送我的初始纹理,然后用glTexSubImage2D更新脏区域。要做到这一点,我正在使用单缓冲。这很有效。

我已经看到使用CVOpenGLESTextureCache可能有另一种方法来实现相同的功能。纹理缓存中保存的纹理引用CVPixelBuffer。我想知道我是否可以改变这些缓存的纹理。我尝试为每次更新重新创建一个CVOpenGLESTexture,但这会大大降低我的帧速率(毕竟因为我没有在任何地方指定脏区域,所以并不奇怪)。也许我完全误解了这个纹理缓存的用例。

有人可以提供一些指导吗?

更新:这是我正在使用的代码。第一次更新工作正常。后续更新不会(没有任何反应)。在每次更新之间,我修改了原始位图。

if (firstUpdate) {

    CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, ctx, NULL, &texCache);

    CVPixelBufferRef pixelBuffer;
    CVPixelBufferCreateWithBytes(NULL, width_, height_, kCVPixelFormatType_32BGRA, bitmap, width_*4, NULL, 0, NULL, &pixelBuffer);
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);

    CVOpenGLESTextureRef texture = NULL;
    CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, texCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture);

    texture_[0] = CVOpenGLESTextureGetName(texture);

    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}


CVOpenGLESTextureCacheFlush(texCache, 0);

if (firstUpdate) {
    glBindTexture(GL_TEXTURE_2D, texture_[0]);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

if (firstUpdate) {
    static const float textureVertices[] = {
        -1.0, -1.0,
        1.0, -1.0,
        -1.0, 1.0,
        1.0, 1.0
    };

    static const float textureCoords[] = {
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        1.0, 1.0
    };

    glVertexPointer(2, GL_FLOAT, 0, &textureVertices[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);
}

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

firstUpdate = false;

1 个答案:

答案 0 :(得分:1)

我一直在使用这些纹理API进行相当多的黑客攻击,我终于能够使用纹理缓存API生成一个通过内存写入纹理的工作示例。这些API可以在iOS设备上运行,但不能在模拟器上运行,因此需要一个特殊的解决方法(基本上只是在模拟器中显式调用glTexSubImage2D())。代码需要双重缓冲在另一个线程中完成的纹理加载,以避免在渲染进行时进行更新。完整的源代码和时序结果为opengl_write_texture_cache。链接的Xcode项目从PNG解码,因此旧iPhone硬件上的性能有点差。但是代码可以自由地做任何你想做的事情,所以不应该很难适应其他像素源。要只写一个脏区域,只写入后台线程中内存缓冲区的那一部分。