Fuck iOS EveryDay

3、离屏渲染原理

2020-07-08  本文已影响0人  花开富贵_cc
常见触发离屏渲染的几种情况:
  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 等)
正常渲染流程

app -> 帧缓冲区(Frame Buffer ) ->Display
APP中的数据经过CPU计算和GPU渲染后,将结果存放在帧缓冲区,利用视频控制器从帧缓冲区中取出,并显示到屏幕上。

离屏渲染流程

app ->离屏缓冲区(OffScreen Buffer)->(图层组合)->帧缓冲区(Frame Buffer )->Display
在图像显示过程中,图像一层一层从帧缓冲区读出,在完成显示后会将其从缓冲区中移除。但是图像往往不是做这么简单的显示,有时还需要对图像进行裁剪等操作。但这些已经从帧缓冲区中移除,再要对其进行操作肯定是无法实现的。所以,为了解决这一问题,添加了离屏缓冲区(offScreen Buffer),每一层图像先分别进行裁剪,存入离屏缓冲区中,然后再将处理好的结果进行合成放入帧缓冲区中。这一操作叫做离屏渲染。
当触发了离屏渲染之后,图像/图形的渲染流程变成了:app进⾏额外的渲染和合并-> offscreen Buffer(离屏缓冲区) 组合. -> FrameBuffer(帧缓冲区) -> 屏幕;特点:(离屏渲染-> 额外的存储空间/offscreen Buffer->FrameBuffer ) offscreenBuffer 空间大小-> 离屏缓冲区的空间最大为屏幕像素点2.5倍
由于离屏渲染中的离屏缓冲区,是额外开辟的一个存储空间,再进行数据转存,所以离屏渲染会影响性能问题


离屏渲染.png

但是一些特殊效果还是要使用离屏渲染

圆角的离屏渲染

1.按钮设置背景图片 开启clipsToBounds或者layer.masksToBounds 会触发离屏渲染

    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn1.frame = CGRectMake(100, 30, 100, 100);
    btn1.layer.cornerRadius = 50;
    [self.view addSubview:btn1];
    
    [btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal];
    btn1.clipsToBounds = YES;

2.按钮不设置背景图片开启clipsToBounds或者layer.masksToBounds不会触发离屏渲染

    UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn2.frame = CGRectMake(100, 180, 100, 100);
    btn2.layer.cornerRadius = 50;
    btn2.backgroundColor = [UIColor blueColor];
    [self.view addSubview:btn2];
    btn2.clipsToBounds = YES;
    UIImageView *img1 = [[UIImageView alloc]init];
    img1.frame = CGRectMake(100, 320, 100, 100);
    img1.backgroundColor = [UIColor blueColor];
    [self.view addSubview:img1];
    img1.layer.cornerRadius = 50;
    img1.layer.masksToBounds = YES;
    img1.image = [UIImage imageNamed:@"btn.png"];

4.UIImageView 只设置了图片,无背景色开启clipsToBounds或者layer.masksToBounds 不会触发离屏渲染

    UIImageView *img2 = [[UIImageView alloc]init];
    img2.frame = CGRectMake(100, 480, 100, 100);
    [self.view addSubview:img2];
    img2.layer.cornerRadius = 50;
    img2.layer.masksToBounds = YES;
    img2.image = [UIImage imageNamed:@"btn.png"];

这里不得不提一下CALayer,它是由backgroundColor、contents、borderWidth&borderColor构成的


E6EAD6AD-4176-4F7D-9CC3-F10032B8B531.png

当我们设置了cornerRadius以及masksToBounds进行圆角+裁剪时,masksToBounds裁剪属性会应用到所有的图层上。
正常渲染流程是依次绘制,绘制完一个图层就可以丢弃了。但现在需要依次在 Offscreen Buffer中保存,等待圆角+裁剪处理,即引发了 离屏渲染 。

总结

光栅化触发离屏渲染

当我们开启光栅化时,会将layer渲染成位图保存在缓存中,这样在下次使用时,就可以直接复用,提高效率。
光栅化使用建议:

上一篇 下一篇

猜你喜欢

热点阅读