7

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

4

1 に答える 1

21

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

1 つ目は、単純にシーンをレンダリングし、シーンglReadPixels()の RGBA データを取得して、次のようにバイト配列に配置するために使用します。

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);

これを行う 2 番目の、より高速な方法は、iOS 5.0 のテクスチャ キャッシュによってテクスチャが提供されている、テクスチャでバックアップされたフレーム バッファ オブジェクト (FBO) にシーンをレンダリングすることです。このアプローチについてはこの回答で説明していますが、生データにアクセスするためのコードは示していません。

テクスチャ キャッシュを設定し、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);

glReadPixels()次に、次のようなものを使用して、このテクスチャ (の RGBA ではなく BGRA 形式) をサポートするバイトから直接読み取ることができます。

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

ただし、OpenGL ES 内で画像を再利用したいだけの場合は、シーンをテクスチャでサポートされた FBO にレンダリングし、そのテクスチャをレンダリングの第 2 レベルで使用するだけです。

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

于 2012-05-04T20:20:53.853 に答える