我试图在iPhone上使用OpenGL ES绘制点精灵。它可能有很多(1000)和64像素宽(也许这就是我的问题 - 是否有限制或者我可以使用太多内存?)
我正在使用CADisplayLink为帧定时。会发生的是,当点数太高或点尺寸太大时,第一个gl绘图函数会延迟或停止。在下面的示例中,glClear()是第一个绘图函数,运行时间可能为0.02秒到0.2秒。如果我只是注释掉glClear,那么glDrawArrays会变成慢速函数(否则运行得非常快)。
这个例子是我为了隔离问题而剥离代码的例子。它只是绘制了一堆点精灵,没有纹理,都在同一个地方。我正在使用VBO存储所有精灵数据(位置,颜色,大小)。这个例子似乎有些过分,但我当然有意在以后修改这些数据。
这是视图的init函数(减去样板文件设置):
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 :(得分:0)
如果glClear()
速度很慢,您可以尝试绘制一个完全覆盖视口区域的大空白四边形。
答案 1 :(得分:0)
您是否正在使用同步(或是否已启用?)。您所看到的延迟可能与CPU和GPU并行运行有关,因此测量单个GL调用的时间没有意义。
如果您正在使用VSync(或GPU负载很重),SwapBuffers调用可能会有一些延迟,因为有些驱动程序会使忙循环等待VBlank。
但首先考虑一下你不应该对单个GL调用进行计时,因为大多数GL调用只是设置GPU的某个状态或写入命令缓冲区,命令执行是异步发生的。