2

iPhoneでOpenGL ESで点スプライトを描こうとしています。それらの数が非常に多く (1000)、幅が最大 64 ピクセルである可能性があります (おそらくそれが私の問題です - 制限があるのでしょうか、それともメモリを使いすぎているのでしょうか?)

フレームの時間を計るために CADisplayLink を使用しています。ポイント数が多すぎるかポイントサイズが大きすぎると、最初の gl 描画関数が遅延または失速する傾向があります。以下の例では、glClear() が最初の描画関数であり、実行に 0.02 秒から 0.2 秒かかる場合があります。単純に glClear をコメントアウトすると、glDrawArrays は遅い関数になります (それ以外の場合は非常に高速に実行されます)。

この例は、問題を切り分けるためにコードを削除したものです。テクスチャなしで、すべて同じ場所に一連のポイント スプライトを描画するだけです。すべてのスプライト データ (位置、色、サイズ) を格納するために VBO を使用しています。この例ではやり過ぎに思えるかもしれませんが、もちろん、後でこのデータを変更するつもりです。

これはビューの init 関数です (ボイラープレートの gl セットアップを除く):

glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);

glDisable(GL_LIGHTING);
glDisable(GL_FOG);

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND); 

glBlendEquationOES(GL_FUNC_ADD_OES);

glClearColor(0.0, 0.0, 0.0, 0.0);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
glEnable(GL_POINT_SPRITE_OES);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
glEnableClientState(GL_COLOR_ARRAY);

glBlendFunc(GL_SRC_ALPHA, GL_ONE);

glEnable(GL_POINT_SMOOTH);

glGenBuffers(1, &vbo);                   // vbo is an instance variable
glBindBuffer(GL_ARRAY_BUFFER, vbo);

glMatrixMode(GL_PROJECTION);
glOrthof(0.0, [self frame].size.width, 0.0, [self frame].size.height, 1.0f, -1.0f);
glViewport(0, 0, [self frame].size.width, [self frame].size.height);  
glMatrixMode(GL_MODELVIEW);

glTranslatef(0.0f, [self frame].size.height, 0.0f);
glScalef(1.0f, -1.0f, 1.0f);  

そして、これはレンダリング関数です:

- (void)render
{
    glClear(GL_COLOR_BUFFER_BIT);    // This function runs slowly!

    int pointCount = 1000;

    // fyi...
    // typedef struct {
    // CGPoint point;
    // CFTimeInterval time;
    // GLubyte r, g, b, a;
    // GLfloat size;
    // } MyPoint;

    glBufferData(GL_ARRAY_BUFFER, sizeof(MyPoint)*pointCount, NULL, GL_DYNAMIC_DRAW);
    MyPoint * vboBuffer = (MyPoint *)glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);

    for (int i = 0; i < pointCount; i++) {
        vboBuffer[i].a = (GLubyte)0xFF;
        vboBuffer[i].r = (GLubyte)0xFF;
        vboBuffer[i].g = (GLubyte)0xFF;
        vboBuffer[i].b = (GLubyte)0xFF;
        vboBuffer[i].size = 64.0;
        vboBuffer[i].point = CGPointMake(200.0, 200.0);
    }

    glUnmapBufferOES(GL_ARRAY_BUFFER);

    glPointSizePointerOES(GL_FLOAT, sizeof(MyPoint), (void *)offsetof(MyPoint, size));
    glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(MyPoint), (void *)offsetof(MyPoint, r));
    glVertexPointer(2, GL_FLOAT, sizeof(MyPoint), (void *)offsetof(MyPoint, point));

    glDrawArrays(GL_POINTS, 0, pointCount);

    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

glClear 関数が停止するのはなぜですか? ランダムな量の遅延だけではありません。ポイント数またはサイズに応じて、同じ間隔 (0.015 秒、0.030 秒、0.045 秒など) でランダムに遅延する傾向があります。また、私が気付いた奇妙なことは、glBlendMode(GL_ZERO, GL_ONE) に切り替えると、問題なく動作することです (ただし、これは私が求めている視覚効果ではありません)。他の glBlendMode 値も同様に速度を変更します - 通常は良い方向に。それはVBOとは何の関係もないので、メモリの問題ではないと思います(そうですか?)。

私は OpenGL の初心者であり、VBO やその他の基本的な概念を誤解している可能性があることを認めます。どんな助けや指導も大歓迎です!

4

2 に答える 2

0

遅い場合glClear()は、ビューポート領域を完全に覆う大きな空白のクワッドを描画してみてください。

于 2010-07-29T23:42:37.107 に答える
0

同期を使用していますか(または有効になっていますか?)表示されている遅延は、CPUとGPUが並行して実行されているという事実に関連している可能性があるため、個々のGL呼び出しの時間を測定しても意味がありません。

VSyncを使用している場合(またはGPUの負荷が高い場合)、一部のドライバーはVBlankを待機するためにビジーループを作成するため、SwapBuffers呼び出しに遅延が発生する可能性があります。

ただし、最初に、個々のGL呼び出しの時間を計るべきではないことを考慮してください。ほとんどのGL呼び出しは、GPUの状態を設定するか、コマンドバッファーに書き込むだけなので、コマンドの実行は非同期で行われます。

于 2010-07-30T15:01:59.920 に答える