美文网首页
iOS 离屏渲染

iOS 离屏渲染

作者: 阿木小丸子 | 来源:发表于2020-07-10 11:41 被阅读0次

    1、什么是离屏渲染?

    在正常情况下,经过CPU的计算以及GPU的渲染之后,会将结果存放到帧缓存区,随后视图控制器会读取帧缓存区的数据,经过数模转换,再逐行显示到屏幕上。
    1.jpeg
    并且在GPU渲染的过程中,一般情况下,会遵循‘画家算法’按次序由远及近的一层一层将结果放置到帧缓存区中,当前帧缓存区的数据显示到屏幕上之后,就会将该帧丢弃,周而复始。
    @图片来自网络.jpeg
    如果我们要对一个多图层的view设置圆角,当我们渲染完图层,要应用一些操作的时候,比如裁剪,之前放置在帧缓存区的数据早已经被丢弃,所以不能同时对多图层进行裁剪操作。
    因此,我们需要开辟一些离屏缓存区来存放一些中间状态的数据,等待全部的图层都渲染到离屏缓存区之后,分别从各个离屏缓存区取出数据,分别做相应的操作(裁剪等)之后,组合存入帧缓存区,再等待屏幕控制器的读取和屏幕刷新。(参考HLinzl)
    3.jpeg

    2、如何检测项目中哪些图层发生了离屏渲染?

    我们先看如下的代码:
    // 有图片
        UIButton *btn1 = [[UIButton alloc]initWithFrame:CGRectMake(100, 40, 60, 60)];
        [btn1 setImage:[UIImage imageNamed:@"test_icon"] forState:UIControlStateNormal];
        btn1.layer.cornerRadius = 30;
        btn1.clipsToBounds = YES;
        [self.view addSubview:btn1];
        
        // 无图片
        UIButton *btn2 = [[UIButton alloc]initWithFrame:CGRectMake(100, 120, 60, 60)];
        btn2.backgroundColor = [UIColor orangeColor];
        btn2.layer.cornerRadius = 30;
        btn2.clipsToBounds = YES;
        [self.view addSubview:btn2];
        
        // 有背景色 + 图片
        UIImageView *imageV1 = [[UIImageView alloc]initWithFrame:CGRectMake(100, 200, 60, 60)];
        imageV1.backgroundColor = [UIColor blueColor];
        imageV1.image = [UIImage imageNamed:@"test_icon"];
        imageV1.layer.cornerRadius = 30;
        imageV1.layer.masksToBounds = YES;
        [self.view addSubview:imageV1];
        
        // 仅有图片
        UIImageView *imageV2 = [[UIImageView alloc]initWithFrame:CGRectMake(100, 200, 60, 60)];
        imageV2.image = [UIImage imageNamed:@"test_icon"];
        imageV2.layer.cornerRadius = 30;
        imageV2.layer.masksToBounds = YES;
        [self.view addSubview:imageV2];
    
    这写代码是我们平时做项目时会经常用到的,但是这些圆角的设置就一定会发生离屏渲染吗?
    接下来,我们在模拟器运行这些代码,打开模拟器的如下设置:
    设置.png
    看,神奇的现象就出现了!
    运行结果.png
    上图的第一个和第三个就发生了离屏渲染

    3、离屏渲染的利弊:

    弊:

    (1)离屏渲染需要额外开辟离屏缓冲区的存储空间,加大了系统的负担,会造成性能上的损耗。而存储空间的大小的上限是2.5倍的屏幕像素大小,一旦超过,则无法使用离屏渲染。
    (2)一旦因为离屏渲染导致最终存入帧缓存区的时候已经超过了16.67ms,则会出现掉帧的情况。

    利:

    (1)在我们项目中有一些特殊的效果(比如一些特殊动画效果),需要额外的缓冲区来保存中间状态,不得不使用离屏渲染。
    (2)如果某一个效果会多次出现在屏幕上,那么可以提前渲染offscreen Buffer ,来达到复用的目的,这样CPU/GPU就不用做一些重复的计算。

    3、离屏渲染的常见触发情况:

    (1) 使用了 mask 的 layer (layer.mask)
    (2) 需要进行裁剪的 layer (layer.masksToBounds /view.clipsToBounds)
    (3) 设置了组透明度为 YES,并且透明度不为 1 的layer (layer.allowsGroupOpacity/ layer.opacity)
    (4) 添加了投影的 layer (layer.shadow*)
    (5) 采用了光栅化的 layer (layer.shouldRasterize)
    (6) 绘制了文字的 layer (UILabel, CATextLayer, Core Text 等)

    相关文章

      网友评论

          本文标题:iOS 离屏渲染

          本文链接:https://www.haomeiwen.com/subject/uzgpcktx.html