2010-07-29 90 views
2

我想在iPhone上用OpenGL ES画点精灵。它可能有很多(1000)和64像素宽(也许这是我的问题 - 有没有限制,或我可以使用太多的内存?)为什么glClear()在iPhone上的点精灵速度缓慢?

我正在使用CADisplayLink到时间框架。会发生什么情况是,当点数过高或点的大小太大时,第一个gl绘图函数往往会延迟或失速。在我的例子中,glClear()是第一个绘图函数,它可以从0.02秒到0.2秒的任何地方运行。如果我只是注释掉glClear,那么glDrawArrays就变成了慢速函数(否则它运行得非常快)。

这个例子是我已经剥离我的代码,以隔离问题。它只是在同一个地方画出一堆点纹,没有纹理。我使用VBOs来存储所有精灵数据(位置,颜色,大小)。这个例子看起来似乎有些过火,但我当然有意在稍后修改这些数据。

这是视图的初始化函数(减去样板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或其他东西的基本概念。任何帮助或指导,非常感谢!

回答

0

如果glClear()很慢,您可以尝试绘制一个完全覆盖视口区域的大型空白四边形。

+0

我确实尝试过,但它看起来并不像glClear那么慢。它似乎是第一个gl绘图函数。如果我摆脱glClear并绘制一个空白四边形,它只会减慢glDrawArrays()。 – 2010-07-30 00:50:34

0

您是否使用同步(或启用了它?)。您看到的延迟可能与CPU和GPU并行运行有关,因此测量各个GL调用的时间没有意义。

如果您使用的是VSync(或者GPU负载过重),SwapBuffers调用中可能会有一些延迟,因为某些驱动程序会导致繁忙循环等待VBlank。

但首先考虑你不应该为每个GL调用调用时间,因为大多数GL调用只是设置GPU的某种状态或写入命令缓冲区,所以命令执行是异步执行的。

+0

这对于不对GL个别GL调用进行计时是有意义的 - 这可能解释了为什么它不一致地运行缓慢。不过,这个问题正在导致FPS的大幅下降(有时低至15fps),所以它不仅仅是测量执行时间的错误。 我没有明确启用或禁用VSync。这是我应该做的事吗? – 2010-07-31 17:09:52