2

我正在尝试在 iPhone 上使用 OpenGL ES 绘制点精灵。它们中可能有很多(1000 个)并且宽度最多为 64 像素(也许这就是我的问题 - 有限制还是我使用了太多的内存?)

我正在使用 CADisplayLink 来计时帧。发生的情况是,当点数太高或点数太大时,第一个 gl 绘图函数往往会延迟或停止。在下面的示例中,glClear() 是第一个绘图函数,它可能需要 0.02 秒到 0.2 秒的时间来运行。如果我简单地注释掉 glClear,glDrawArrays 就会成为慢速函数(否则它会运行得非常快)。

这个例子是我为了隔离问题而将我的代码剥离出来的。它只是在同一个位置绘制了一堆没有纹理的点精灵。我正在使用 VBO 来存储所有精灵数据(位置、颜色、大小)。对于这个例子来说,这似乎有点矫枉过正,但我​​当然打算稍后修改这些数据。

这是视图的初始化函数(减去样板 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

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

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

但首先考虑你不应该对单个 GL 调用计时,因为大多数 GL 调用只是设置 GPU 的某些状态或写入命令缓冲区,命令执行是异步发生的。

于 2010-07-30T15:01:59.920 回答
0

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

于 2010-07-29T23:42:37.107 回答