2012-10-10 52 views
1

我的OpenGL應用程序使用OpenGL以全屏方式渲染紋理並定期更新其中的一部分。到目前爲止,我一直在使用glTexImage2D來推送我的初始紋理,然後使用glTexSubImage2D更新髒區域。爲此,我使用單緩衝。這很好。iOS上的CVOpenGLESTextureCache vs 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; 
+0

是的,你真的不想爲每次更新重新創建緩存的紋理或像素緩衝區,而是創建一次並將其用於更新。在創建這個像素緩衝區和紋理時有一些開銷。一旦你有了紋理,你應該能夠通過寫入像素緩衝區的字節來更新它,因爲它們應該直接映射到紋理的內部字節。 –

+0

這就是我的想法,但無法得到這個工作......我設法通過將我的位圖包裹在像素緩衝區中來將我的初始紋理推到屏幕上。然後我保留紋理緩存,紋理本身和像素緩衝區。接下來我要做的是更新我的底層位圖並重繪我的OpenGL四邊形。然而,什麼都沒有發生...... – user1727274

+0

我已經測試了我能想到的每一個變體,並且在Sim,iPhone4和iPad2上發現了與您相同的結果。使用CVPixelBufferCreate()或CVPixelBufferCreateWithBytes()來創建cv緩衝區似乎並不重要。調用CVPixelBufferCreateWithBytes將上傳1幀(用戶緩衝區的初始狀態),但寫入映射的數據存儲器不起作用。實際上,我發現如果你在每一幀都刪除並重新創建紋理,那麼CVOpenGLESTextureCacheCreateTextureFromImage()API只需花費所有時間在glTexImage2D_Exec上進行。 – MoDJ

回答

1

我已經做了不少與這些質地的API盜號的,我終於能夠產生使用紋理緩存API通過存儲器寫入到紋理的工作示例。這些API可以在iOS設備上工作,但不能在模擬器上工作,所以需要特殊的解決方法(基本上只需在模擬器中明確調用glTexSubImage2D())。代碼需要加倍緩衝在另一個線程中完成的紋理加載,以避免在渲染過程中進行更新。完整的源代碼和時間結果在opengl_write_texture_cache。鏈接的Xcode項目從PNG解碼,因此舊iPhone硬件的性能稍差。但是代碼可以自由地做任何你想做的事情,所以它不應該很難適應其他像素源。要僅寫入髒區域,只能在後臺線程中寫入內存緩衝區的那一部分。