Arc*_*gon 7 opengl-es core-graphics vector-graphics openvg ios
我正在开发一个iOS应用程序,需要实时绘制Bézier曲线以响应用户的输入.起初,我决定尝试使用CoreGraphics,它具有出色的矢量绘图API.然而,我很快就发现性能很痛苦,极其缓慢,在我的视网膜iPad上只有一条曲线,帧速率开始严重下降.(不可否认,这是一个代码效率低下的快速测试.例如,曲线每帧都重新绘制.但是今天的计算机确实足够快,每隔1/60秒处理一条简单的曲线,对吧?!)
在这个实验之后,我切换到OpenGL和MonkVG库,我感到非常高兴.我现在可以在没有任何帧速率下降的情况下同时渲染HUNDREDS曲线,对保真度的影响很小(对于我的用例).
更新:
我编写了一个快速测试应用程序来更准确地衡量性能.下面是我的自定义CALayer子类的代码.
将NUM_PATHS设置为5并将NUM_POINTS设置为15(每个路径5个曲线段),代码在非视网膜模式下以20fps运行,在iPad 3上以视网膜模式运行6fps.分析器将CGContextDrawPath列为拥有96%的CPU时间.是的 - 显然,我可以通过限制我的重绘矩形进行优化,但如果我真的需要60fps的全屏矢量动画呢?
OpenGL在早餐时吃这个测试.矢量绘图怎么可能这么慢?
#import "CGTLayer.h"
@implementation CGTLayer
- (id) init
{
self = [super init];
if (self)
{
self.backgroundColor = [[UIColor grayColor] CGColor];
displayLink = [[CADisplayLink displayLinkWithTarget:self selector:@selector(updatePoints:)] retain];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
initialized = false;
previousTime = 0;
frameTimer = 0;
}
return self;
}
- (void) updatePoints:(CADisplayLink*)displayLink
{
for (int i = 0; i < NUM_PATHS; i++)
{
for (int j = 0; j < NUM_POINTS; j++)
{
points[i][j] = CGPointMake(arc4random()%768, arc4random()%1024);
}
}
for (int i = 0; i < NUM_PATHS; i++)
{
if (initialized)
{
CGPathRelease(paths[i]);
}
paths[i] = CGPathCreateMutable();
CGPathMoveToPoint(paths[i], &CGAffineTransformIdentity, points[i][0].x, points[i][0].y);
for (int j = 0; j < NUM_POINTS; j += 3)
{
CGPathAddCurveToPoint(paths[i], &CGAffineTransformIdentity, points[i][j].x, points[i][j].y, points[i][j+1].x, points[i][j+1].y, points[i][j+2].x, points[i][j+2].y);
}
}
[self setNeedsDisplay];
initialized = YES;
double time = CACurrentMediaTime();
if (frameTimer % 30 == 0)
{
NSLog(@"FPS: %f\n", 1.0f/(time-previousTime));
}
previousTime = time;
frameTimer += 1;
}
- (void)drawInContext:(CGContextRef)ctx
{
// self.contentsScale = [[UIScreen mainScreen] scale];
if (initialized)
{
CGContextSetLineWidth(ctx, 10);
for (int i = 0; i < NUM_PATHS; i++)
{
UIColor* randomColor = [UIColor colorWithRed:(arc4random()%RAND_MAX/((float)RAND_MAX)) green:(arc4random()%RAND_MAX/((float)RAND_MAX)) blue:(arc4random()%RAND_MAX/((float)RAND_MAX)) alpha:1];
CGContextSetStrokeColorWithColor(ctx, randomColor.CGColor);
CGContextAddPath(ctx, paths[i]);
CGContextStrokePath(ctx);
}
}
}
@end
Run Code Online (Sandbox Code Playgroud)
首先,请参阅为什么 UIBezierPath 比 Core Graphics 路径更快?并确保您正在以最佳方式配置路径。默认情况下,CGContext
向路径添加许多“漂亮”选项,这会增加大量开销。如果您关闭这些功能,您可能会发现速度显着提高。
我在 Core Graphics B\xc3\xa9zier 曲线中发现的下一个问题是,当单条曲线中有许多组件时(当我检查大约 3000-5000 个元素时,我发现了问题)。我发现花在上面的时间非常惊人CGPathAdd...
。减少路径中的元素数量可能是一个重大胜利。从我去年与 Core Graphics 团队的谈话来看,这可能是 Core Graphics 中的一个错误,并且可能已被修复。我没有重新测试过。
编辑:通过进行以下更改,我在 iPad 3 上的 Retina 中看到 18-20FPS:
\n\n移动CGContextStrokePath()
循环之外。你不应该抚摸每条路。最后应该抚摸一次。这使我的测试从 ~8FPS 到 ~12FPS。
关闭抗锯齿功能(在 OpenGL 测试中可能默认关闭):
\n\nCGContextSetShouldAntialias(ctx, false);\n
Run Code Online (Sandbox Code Playgroud)\n\n这使我的帧速率达到 18-20FPS(视网膜),非视网膜帧速率高达 40FPS 左右。
\n\n我不知道你在 OpenGL 中看到了什么。请记住,Core Graphics 的设计目的是让事物变得美丽;OpenGL 旨在让事情变得更快。Core Graphics依赖于OpenGL;所以我总是期望编写良好的 OpenGL 代码会更快。
\n 归档时间: |
|
查看次数: |
4057 次 |
最近记录: |