ios - 非常慢的软件矢量,尤其是 CoreGraphics 与 OpenGL

标签 ios opengl-es core-graphics vector-graphics openvg

我正在开发一个 iOS 应用程序,它需要实时绘制贝塞尔曲线以响应用户的输入。起初,我决定尝试使用 CoreGraphics,它具有出色的矢量绘图 API。然而,我很快发现性能非常缓慢,令人痛苦,以至于帧率开始严重下降,我的视网膜 iPad 上只有一条曲线。 (不可否认,这是一个使用低效代码的快速测试。例如,曲线每帧都被重新绘制。但今天的计算机肯定足够快,可以处理每 1/60 秒绘制一条简单曲线,对吧?!)

在这个实验之后,我切换到 OpenGL 和 MonkVG图书馆,我再高兴不过了。我现在可以同时渲染数百条曲线,而不会降低帧率,而且对保真度的影响很小(对于我的用例)。

  1. 是否有可能我以某种方式滥用了 CoreGraphics(以至于它比 OpenGL 解决方案慢了几个数量级),或者性能真的有那么糟糕吗?根据 StackOverflow/论坛关于 CG 性能的问题和答案的数量,我的预感是问题出在 CoreGraphics 上。 (我见过几个人说 CG 不应该进入运行循环,它应该只用于不频繁的渲染。)从技术上讲,为什么会这样?
  2. 如果 CoreGraphics 真的那么慢,那么 Safari 究竟是如何运行得如此流畅的呢?我的印象是 Safari 没有硬件加速,但它必须同时显示数百个(如果不是数千个)矢量字符而不丢帧。
  3. 更一般地说,使用大量矢量的应用程序(浏览器、Illustrator 等)如何在没有硬件加速的情况下保持如此快速? (据我了解,许多浏览器和图形套件现在都带有硬件加速选项,但默认情况下通常不会打开。)

更新:

我编写了一个快速测试应用程序来更准确地衡量性能。下面是我的自定义 CALayer 子类的代码。

NUM_PATHS 设置为 5,NUM_POINTS 设置为 15(每条路径 5 个曲线段),代码在我的 iPad 3 上以非视网膜模式以 20fps 运行,以视网膜模式以 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

最佳答案

您真的不应该将 Core Graphics 绘图与 OpenGL 进行比较,您是在出于非常不同的目的比较完全不同的功能。

在图像质量方面,Core Graphics 和 Quartz 将以更少的努力远远优于 OpenGL。 Core Graphics 框架旨在实现最佳外观、自然抗锯齿的线条和曲线以及与 Apple UI 相关的润色。但这种图像质量是有代价的:渲染速度。

另一方面,OpenGL 的设计优先考虑速度。高性能、快速绘图是 OpenGL 难以匹敌的。但这种速度是有代价的:使用 OpenGL 获得平滑和优美的图形要困难得多。有许多不同的策略可以在 OpenGL 中执行像抗锯齿这样“简单”的操作,Quartz/Core Graphics 更容易处理。

关于ios - 非常慢的软件矢量,尤其是 CoreGraphics 与 OpenGL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15370344/

相关文章:

iphone - 有没有适合初学者的关于Core Graphics的好资料?

ios - CIColor 到 UIColor -> CIColor 没有为 UIColor UIExtendedSRGBColorSpace 定义

ios - 调用出队单元格时出队可重用单元格崩溃

ios - 用渐变色 SWIFT 填充未定义的表格

iphone - 仅使用 Core Graphics 和 CADisplayLink 的图像动画示例

ios - 模拟器崩溃 "[NSMutableArray insertObject:atIndex:]: attempt to insert nil object at 0'”

ios - 更换Vuforia中的茶壶

iphone - 将 iPhone 3-D 游戏代码转换为在 Android 设备上运行的最佳方式?

android - 渲染图像的随机消失部分

ios - 快速创建一个只有两个圆角的矩形?