iOS 上的 CVOpenGLESTextureCache 与 glTexSubImage2D [英] CVOpenGLESTextureCache vs glTexSubImage2D on iOS

查看:14
本文介绍了iOS 上的 CVOpenGLESTextureCache 与 glTexSubImage2D的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 OpenGL 应用程序使用 OpenGL 全屏渲染纹理并定期更新其中的一部分.到目前为止,我一直在使用 glTexImage2D 推送我的初始纹理,然后使用 glTexSubImage2D 更新脏区域.为此,我使用单缓冲.这很好用.

My OpenGL app uses OpenGL to render a texture in full screen and updates part of it at regular intervals. So far, I've been using glTexImage2D to push my initial texture and then I update the dirty regions with glTexSubImage2D. To do that, I'm using single buffering. This works well.

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

I've seen that there might be another way to achieve the same thing using CVOpenGLESTextureCache. The textures held in the texture cache reference a CVPixelBuffer. I'd like to know if I can mutate these cached textures. I tried to recreate a CVOpenGLESTexture for each update but this decreases my frame rate dramatically (not surprising after all since I'm not specifying the dirty region anywhere). Maybe I totally misunderstood the use case for this texture cache.

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

Can someone provide some guidance?

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

UPDATE: Here is the code I'm using. The first update works fine. The subsequent updates don't (nothing happens). Between each update I modify the raw bitmap.

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;

推荐答案

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

I have been doing quite a bit of hacking with these texture APIs and I finally was able to produce a working example of writing to a texture via memory using the texture cache API. These APIs work on the iOS device but not on the simulator, so a special workaround was needed (basically just calling glTexSubImage2D() explicitly in the simulator). The code needed to double buffer the texture loading done in another thread to avoid updating while rendering was going on. The full source code and timing results are at opengl_write_texture_cache. The linked Xcode project decodes from PNGs and the performance on older iPhone hardware is a little poor as a result. But the code is free to do whatever you want with, so it should not be hard to adapt to some other pixel source. To only write a dirty region, only write to that portion of the memory buffer in the background thread.

这篇关于iOS 上的 CVOpenGLESTextureCache 与 glTexSubImage2D的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆