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 やその他の基本的な概念を誤解している可能性があることを認めます。どんな助けや指導も大歓迎です!