2011-01-27 12 views
10

私は現在、物理シミュレーションをiPhone自体のビデオに変換するプロジェクトに取り組んでいます。OpenGL to iPhone on

これを行うには、私は現在2つの異なるループを使用しています。最初のループは、AVAssetWriterInputオブジェクトがEAGLViewをポーリングしてより多くのイメージを取得するブロックで実行されます。 EAGLViewは、格納されている配列からイメージを提供します。

もう1つのループが実際のシミュレーションです。シミュレーションタイマーをオフにして、毎回あらかじめ指定された時間差でチックを呼びます。目盛りが呼び出されるたびに、バッファがスワップされた後、EAGLViewのスワップバッファメソッドで新しいイメージを作成します。このイメージは、AVAssetWriterがポーリングする配列に配置されます。

配列が大きすぎる

を取得していないこのすべてが正常に動作しますが、非常に非常に遅いことを確認するためにいくつかの雑多なコードもあります。

私はそれが概念的に何かしているのですか?プロセス全体がそれよりも遅くなる原因になりますか?また、OpenGLのイメージをglReadPixelsよりも速く取得する方法を知っている人はいますか?

+0

一番大事なのは、どのような関数呼び出しが最も時間を費やしているのかを自分で証明するためにInstruments(Time Profiler、Shark)を使ったことがありますか? – makdad

答えて

3

ビデオメモリは、書き込みが速く、読み込みが遅くなるように設計されています。だから私はテクスチャにレンダリングを実行します。ここで私はテクスチャにシーンをレンダリングするために作成した全体の方法は、(そこにいくつかのカスタムコンテナがありますが、私はそれはあなた自身でそれらを置き換えるために非常に簡単だと思う)です。もちろん

-(TextureInf*) makeSceneSnapshot { 
    // create texture frame buffer 
    GLuint textureFrameBuffer, sceneRenderTexture; 

    glGenFramebuffersOES(1, &textureFrameBuffer); 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer); 

    // create texture to render scene to 
    glGenTextures(1, &sceneRenderTexture); 
    glBindTexture(GL_TEXTURE_2D, sceneRenderTexture); 

    // create TextureInf object 
    TextureInf* new_texture = new TextureInf(); 
    new_texture->setTextureID(sceneRenderTexture); 
    new_texture->real_width = [self viewportWidth]; 
    new_texture->real_height = [self viewportHeight]; 

    //make sure the texture dimensions are power of 2 
    new_texture->width = cast_to_power(new_texture->real_width, 2); 
    new_texture->height = cast_to_power(new_texture->real_height, 2); 

    //AABB2 = axis aligned bounding box (2D) 
    AABB2 tex_box; 

    tex_box.p1.x = 1 - (GLfloat)new_texture->real_width/(GLfloat)new_texture->width; 
    tex_box.p1.y = 0; 
    tex_box.p2.x = 1; 
    tex_box.p2.y = (GLfloat)new_texture->real_height/(GLfloat)new_texture->height; 
    new_texture->setTextureBox(tex_box); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, new_texture->width, new_texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, sceneRenderTexture, 0); 

    // check for completness 
    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { 
     new_texture->release(); 
     @throw [NSException exceptionWithName: EXCEPTION_NAME 
             reason: [NSString stringWithFormat: @"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)] 
            userInfo: nil]; 
     new_texture = nil; 
    } else { 
     // render to texture 
     [self renderOneFrame]; 
    } 

    glDeleteFramebuffersOES(1, &textureFrameBuffer); 

    //restore default frame and render buffers 
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, _defaultFramebuffer); 
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, _colorRenderbuffer); 
    glEnable(GL_BLEND);   
    [self updateViewport];  
    glMatrixMode(GL_MODELVIEW); 


    return new_texture; 
} 

、あなたが」スナップショットを常時行っている場合は、テクスチャフレームとレンダリングバッファを一度作成して(それらのメモリを割り当てるだけでよい)

1

GPUはCPUとは非同期で動作しているため、レンダリングが終了した直後にglReadPixelsを実行しようとすると、コマンドがGPUにフラッシュされてレンダリングされるのを待たなければなりませんそれらを読み取ることができます。

同期待ちではなく、スナップショットをテクスチャのキューに(MaxなどのFBOを使用して)レンダリングします。前のフレームの1つをデキューする前に、さらに2つのフレームをレンダリングするまで待ちます。 iPhoneがフェンスやオブジェクトの同期をサポートしているかどうかは分かりませんが、もしそうなら、ピクセルを読み取る前にレンダリングが終了したかどうかを確認できます。

1

CADisplayLinkオブジェクトを使用して、描画レートとキャプチャレートがデバイスの画面更新レートに対応するようにすることができます。実行中のループの実行時間を遅くすると、デバイスの画面リフレッシュごとにリフレッシュとキャプチャが多すぎる可能性があります。

あなたのアプリの目標に応じて、あなたが提示するすべてのフレームをキャプチャする必要はない可能性があるため、セレクタで現在のフレームをキャプチャするかどうかを選択できます。

0

質問は新しいものではないが、ので、私は、私はピッチだろうと思って、まだ答えていない。

glReadPixelsは確かに非常に遅いので、adverslyせずにOpenGLアプリケーションからの映像を記録するために使用することはできませんパフォーマンスに影響を与えます。

回避策を見つけて、OpenGLベースのグラフィックをビデオファイルに記録できるEveryplayという無料のSDKを、パフォーマンスの低下なしで作成しました。https://developers.everyplay.com/