2012-05-04 16 views
5

iOS上にOpenGL ES 2次元レンダラを書く必要があります。それは線やポリゴンのようないくつかのプリミティブを2D画像に描画する必要があります(ベクトルマップのレンダリングになります)。どのようにOpenGLのコンテキストからそのタスクのイメージを取得するためのベストですか?私は、これらのプリミティブをテクスチャにレンダリングし、それからイメージを取得するのか、それとも何か?また、必要なもののように見えるサンプルやチュートリアルを誰かが提供してくれれば(2d GLの画像をレンダリングする)ことは素晴らしいことです。前もって感謝します!OpenGL ESイメージへの2dレンダリング

答えて

19

OpenGL ES 2次元シーンをレンダリングし、そのシーンの画像を抽出してOpenGL ESの外で使用する場合、2つの主要なオプションがあります。はるかに高速

GLubyte *rawImagePixels = (GLubyte *)malloc(totalBytesForImage); 
glReadPixels(0, 0, (int)currentFBOSize.width, (int)currentFBOSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels); 
// Do something with the image 
free(rawImagePixels); 

秒、および、方法:

最初は単にあなたのシーンをレンダリングし、シーンのRGBAデータを取得し、以下のように、バイト配列に配置するglReadPixels()を使用することですこれを行うには、テクスチャがiOS 5.0のテクスチャキャッシュによって提供されている、テクスチャに裏打ちされたフレームバッファオブジェクト(FBO)にシーンをレンダリングする必要があります。私はこのアプローチをthis answerに記述していますが、そこに生データアクセスのコードは示していません。

あなた行うテクスチャキャッシュを設定し、FBOテクスチャバインドするには、次

CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, (__bridge void *)[[GPUImageOpenGLESContext sharedImageProcessingOpenGLESContext] context], NULL, &rawDataTextureCache); 
    if (err) 
    { 
     NSAssert(NO, @"Error at CVOpenGLESTextureCacheCreate %d"); 
    } 

    // Code originally sourced from http://allmybrain.com/2011/12/08/rendering-to-a-texture-with-ios-5-texture-cache-api/ 

    CFDictionaryRef empty; // empty value for attr value. 
    CFMutableDictionaryRef attrs; 
    empty = CFDictionaryCreate(kCFAllocatorDefault, // our empty IOSurface properties dictionary 
           NULL, 
           NULL, 
           0, 
           &kCFTypeDictionaryKeyCallBacks, 
           &kCFTypeDictionaryValueCallBacks); 
    attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 
             1, 
             &kCFTypeDictionaryKeyCallBacks, 
             &kCFTypeDictionaryValueCallBacks); 

    CFDictionarySetValue(attrs, 
         kCVPixelBufferIOSurfacePropertiesKey, 
         empty); 

    //CVPixelBufferPoolCreatePixelBuffer (NULL, [assetWriterPixelBufferInput pixelBufferPool], &renderTarget); 

    CVPixelBufferCreate(kCFAllocatorDefault, 
         (int)imageSize.width, 
         (int)imageSize.height, 
         kCVPixelFormatType_32BGRA, 
         attrs, 
         &renderTarget); 

    CVOpenGLESTextureRef renderTexture; 
    CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault, 
                rawDataTextureCache, renderTarget, 
                NULL, // texture attributes 
                GL_TEXTURE_2D, 
                GL_RGBA, // opengl format 
                (int)imageSize.width, 
                (int)imageSize.height, 
                GL_BGRA, // native iOS format 
                GL_UNSIGNED_BYTE, 
                0, 
                &renderTexture); 
    CFRelease(attrs); 
    CFRelease(empty); 
    glBindTexture(CVOpenGLESTextureGetTarget(renderTexture), CVOpenGLESTextureGetName(renderTexture)); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(renderTexture), 0); 

をして、あなただけではなく、RGBAのBGRAフォーマットで(このテクスチャをバックアップバイトから直接読み取ることができますglReadPixels())のようなもの使用して:あなただけのOpenGL ESの中にあなたのイメージを再利用したい場合は、あなただけのテクスチャ担保FBOに、あなたのシーンをレンダリングする必要があり、その後の2番目のレベルでそのテクスチャを使用

CVPixelBufferLockBaseAddress(renderTarget, 0); 
    _rawBytesForImage = (GLubyte *)CVPixelBufferGetBaseAddress(renderTarget); 
    // Do something with the bytes 
    CVPixelBufferUnlockBaseAddress(renderTarget, 0); 

をレンダリング。

これを実際に見たい場合は、オープンソースGPUImageフレームワーク内のCubeExampleサンプルアプリケーション内で、テクスチャにレンダリングし、その上で何らかの処理を実行する例を示します。

+0

ありがとうございますが、これはiOS 5でのみ動作しますか? – medvedNick

+0

@medvedNick - 'glReadPixels()'はすべてのOSバージョンで動作しますが、テクスチャキャッシュはiOS 5.0で初めて導入されました。彼らははるかに高速ですが、5.0のみです。あなたはランタイムチェックを行うことができ、古いOSバージョンではより遅い 'glReadPixels()'にフォールバックすることができます。ここでもGPUImageコードをチェックしてください。 –

+0

テクスチャキャッシュは5.0以上ですが、特定のデバイスで高速ではありませんか?例えば4S/iPad2で高速化し、どこでもglReadPixels/glTexImage2Dに相当します。 –

関連する問題