【发布时间】:2015-08-14 10:51:26
【问题描述】:
我有一个基于 OpenGL ES 2.0 的动画背景层,我使用 GLKView 作为图形容器,使用 GLKViewController 作为控制器。对于绘图,我使用 GLKBaseEffect。
我介绍了一个 sprite 类,它可以将 png 文件作为纹理加载、操作 sprite (SRT) 和一些附加属性,如 alpha 混合等。
我想知道如何优化我的程序,因为当我的 iPhone 4S 显示 50 个大小为 128x128 像素的精灵(都具有相同的纹理/png 文件!)时,帧速率下降到大约 25 FPS .
在以下部分中,我列出了该程序的重要部分。目前,我为每个帧的 50 个精灵中的每一个调用 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)(目标帧速率为 60);这相当于每秒 3000 次调用。
这可能是瓶颈吗?我该如何优化呢?
这就是我初始化精灵数组 (GLKViewController.m) 的方式:
- (void)initParticles {
if(sprites==nil) {
sprites = [NSMutableArray array];
for (int i=0; i<50; i++) {
Sprite* sprite = [[Sprite alloc] initWithFile:@"bubble" extension:@"png" effect:effect];
// configure some sprite properties [abbreviated]
[sprites addObject:sprite];
}
}
}
这是渲染函数(GLKViewController.m):
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
glClearColor(0.0, 0.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
// render the bubbles
for (Sprite* sprite in sprites) {
[sprite render];
}
}
下面是精灵类(Sprite.m)的一些重要部分:
- (id)initWithFile:(NSString *)filename extension:(NSString*)extension effect:(GLKBaseEffect *)effect {
if(self = [self init]) {
self.effect = effect;
NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], GLKTextureLoaderOriginBottomLeft, nil];
NSError* error = nil;
NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:nil];
self.textureInfo = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error];
if (self.textureInfo == nil) {
NSLog(@"Error loading file: %@", [error localizedDescription]);
return nil;
}
TexturedQuad newQuad;
newQuad.bl.geometryVertex = GLKVector2Make(0, 0);
newQuad.br.geometryVertex = GLKVector2Make(self.textureInfo.width, 0);
newQuad.tl.geometryVertex = GLKVector2Make(0, self.textureInfo.height);
newQuad.tr.geometryVertex = GLKVector2Make(self.textureInfo.width, self.textureInfo.height);
newQuad.bl.textureVertex = GLKVector2Make(0, 0);
newQuad.br.textureVertex = GLKVector2Make(1, 0);
newQuad.tl.textureVertex = GLKVector2Make(0, 1);
newQuad.tr.textureVertex = GLKVector2Make(1, 1);
self.quad = newQuad;
}
return self;
}
- (void)render {
[self applyBaseEffect];
long offset = (long)&_quad;
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void*) (offset + offsetof(TexturedVertex, geometryVertex)));
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void*) (offset + offsetof(TexturedVertex, textureVertex)));
glBlendColor(1.0, 1.0, 1.0, self.alpha);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
}
- (void)applyBaseEffect {
self.effect.texture2d0.name = self.textureInfo.name;
self.effect.texture2d0.envMode = GLKTextureEnvModeModulate;
self.effect.texture2d0.target = GLKTextureTarget2D;
self.effect.texture2d0.enabled = GL_TRUE;
self.effect.useConstantColor = GL_TRUE;
self.effect.constantColor = GLKVector4Make(self.tint.r*self.alpha, self.tint.g*self.alpha, self.tint.b*self.alpha, self.alpha);
self.effect.transform.modelviewMatrix = GLKMatrix4Multiply(GLKMatrix4Identity, [self modelMatrix]);
[self.effect prepareToDraw];
}
- (GLKMatrix4)modelMatrix {
GLKMatrix4 modelMatrix = GLKMatrix4Identity;
modelMatrix = GLKMatrix4Translate(modelMatrix, self.position.x, self.position.y, 0);
modelMatrix = GLKMatrix4Rotate(modelMatrix, self.rotation, 0, 0, 1);
modelMatrix = GLKMatrix4Scale(modelMatrix, self.scale, self.scale, 0);
modelMatrix = GLKMatrix4Translate(modelMatrix, -self.normalSize.width/2, -self.normalSize.height/2, 0);
return modelMatrix;
}
EDIT-1:以下是一些性能指标(似乎受 GPU 限制)
EDIT-2:当我添加 view.drawableMultisample 行时,我的 iPhone 4S 上的帧速率从 25 提高到 45,无论我使用哪条行(无 / 4x)。奇怪 - 我的渲染代码似乎不受 MSAA 影响,相反。
GLKView *view = (GLKView*)self.view;
view.context = context;
view.drawableMultisample = GLKViewDrawableMultisampleNone;
//view.drawableMultisample = GLKViewDrawableMultisample4x;
【问题讨论】:
-
精灵是否具有相同的特征(顶点、纹理等)?
-
您需要先进行分析才能知道您的应用程序是 CPU 还是 GPU 绑定。请检查this 然后从 XCode 运行您的应用程序并在此处添加结果的屏幕截图。我想查看“利用率”和“帧时间”的值
-
是的,您受 GPU 限制,但更准确地说,GPU 受片段着色器/光栅化部分的限制。稍后我会尝试写一个详细的答案。但基本上这意味着你的片段着色器太复杂和/或你有太多的屏幕表面被使用 alpha 混合的四边形占用(带有大量过度绘制的 alpha 混合是 iPhone4 / 4S 上的性能杀手,alpha 混合四边形的成本要高得多比不透明的)。您还启用了 MSAA 吗?如果您在低端 IOS 设备上以 60fps 为目标,则不建议使用 MSAA。
-
我不明白你的 MSAA 结果,你是说 GLKViewDrawableMultisampleNone 给你 45 fps 而 GLKViewDrawableMultisample4x 给你 25 fps 吗?或者仅仅是为 view.drawableMultisample 设置一个值就可以提高你的 fps(这似乎不太可能......)?
-
另外,我认为问题主要来自您的背景。它的着色器对于低端 IOS 来说太重了(我知道它没有太多,但这已经太多了……)。既然这只是一个“静态背景”,为什么不直接使用预制纹理而不是着色器呢?请注意,通过使用帧缓冲区对象,您可以使用着色器“渲染到纹理”背景,然后将此纹理用作背景(因此纹理将由代码生成......)。最后一件事:请确保在渲染背景时禁用 alpha 混合(我认为不需要它)
标签: ios opengl-es opengl-es-2.0