1

我的 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;
4

1 回答 1

1

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

于 2013-08-24T05:22:37.737 回答