0
点赞
收藏
分享

微信扫一扫

iOS 离屏渲染

芭芭蘑菇 2021-09-19 阅读 118
OC

前言:Debug->Color Off-screen Rendered

eg:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //1、按钮背景图片(出现离屏渲染)
    UIButton *btn1 = [UIButton new];
    btn1.frame = CGRectMake(100, 30, 100, 100);
    btn1.layer.cornerRadius = 50;
    [self.view addSubview:btn1];
    [btn1 setImage:[UIImage imageNamed:@"sun.png"] forState:UIControlStateNormal];
    btn1.clipsToBounds = YES;
    
    //2、按钮背景色
    UIButton *btn2 = [UIButton new];
    btn2.frame = CGRectMake(100, 30+100, 100, 100);
    btn2.layer.cornerRadius = 50;
    btn2.backgroundColor = [UIColor blueColor];
    [self.view addSubview:btn2];
    btn2.clipsToBounds = YES;
    
    //3、UIImageView 设置图片+背景色(出现离屏渲染)
    UIImageView *img = [UIImageView new];
    img.frame = CGRectMake(100, 30+200, 100, 100);
    img.layer.cornerRadius = 50;
    img.layer.masksToBounds = YES;//img.clipsToBounds = YES;
    [self.view addSubview:img];
    img.backgroundColor = [UIColor blueColor];
    img.image = [UIImage imageNamed:@"sun.png"];
    
    //4、UIImageView 设置图片
    UIImageView *img2 = [UIImageView new];
    img2.frame = CGRectMake(100, 30+300, 100, 100);
    img2.layer.cornerRadius = 50;
    img2.layer.masksToBounds = YES;//img.clipsToBounds = YES;
    [self.view addSubview:img2];
    img2.image = [UIImage imageNamed:@"sun.png"];
}

1、离屏渲染产生的原因

正常渲染(遵循油画算法):APP -> Frame Buffer -> Display
图层叠加的油画算法:

图层的叠加绘制大概遵循“画家算法”。
油画算法:先绘制场景中的离观察者较远的物体,再绘制较近的物体。


离屏渲染:APP -> Offscreen Buffer -> Display



离屏渲染产生的原因:当帧缓冲区的图片不能直接展示在屏幕上,需要经过其他的混合处理/计算(比如遮罩、半透明颜色混合),就必须把他们放到离屏缓冲区,经过计算后再展示在屏幕上。
3、离屏渲染的影响(离屏渲染会消耗性能,容易掉帧)

它要创建一个新的缓冲区(OffScreen Buffer,空间限制是屏幕像素的2.5倍),然后还需要上下文环境,在离屏渲染的整个过程中需要切换上下文环境,从当前屏幕切换到离屏,等结束后,又将上下文切换回来。

二、离屏渲染的情况和解决办法

1、圆角触发离屏渲染的真正原因

当我们设置layer.cornerRadius以及maskToBounds/clipsToBounds的时候



设置layer.cornerRadius只会设置backgroundcolor和border的圆角,不会设置content的圆角。如果再加上maskToBounds/clipsToBounds就会设置content的圆角。

本来遵循油画算法从后往前绘制完一个图层就可以丢弃了,但是现在因为要处理背景颜色和content的圆角(你没办法单独对content进行圆角+裁剪设置,一定是结合了所在视图的大小你才知道content要裁剪成什么样子的)

我们需要将其依次在Offscreen Buffer中保存,对混合背景颜色+content的图进行圆角处理,就触发了离屏渲染。
2、离屏渲染的其他情况

1、mask遮罩(类似毛玻璃效果)-> 使用混合图层,在layer上方叠加相应mask形状的半透明layer

2、edge antialiasing(抗锯齿) -> 不设置 allowsEdgeAntialiasing 属性为YES(默认为NO)

  1. allowsGroupOpacity(组不透明,开启CALayer的allowsGroupOpacity属性后,子 layer 在视觉上的透明度的上限是其父 layer 的opacity(对应UIView的alpha),并且从 iOS 7 以后默认全局开启了这个功能,这样做是为了让子视图与其容器视图保持同样的透明度。) ->关闭 allowsGroupOpacity 属性,按产品需求自己控制layer透明度

4.shadows(阴影)-> 设置阴影后,设置CALayer的 shadowPath.view.layer.shadowPath=[UIBezierPath pathWithCGRect:view.bounds].CGPath;

5、shouldRasterize (光栅化)
三、怎么使用离屏渲染优化性能

shouldRasterize = YES在其他属性触发离屏渲染的同时,会将光栅化后的内容缓存起来,如果对应的layer及其sublayers没有发生改变,在下一帧的时候可以直接复用。【可以开启“Color Hits Green and Misses Red”来检查该场景下光栅化操作是否是一个好的选择,绿色则表示光栅化图层被复用,红色则无】

shouldRasterize (光栅化使用建议):

1.如果layer不需要复用,则没有必要打开

2.如果layer不是静态的,需要被频繁修改,比如出于动画之中,则开启光栅华反而影响性能

3.离屏渲染缓存有时间限制,当超过100ms,内容没有被使用就会被丢弃,无法复用

4.离屏渲染缓存有空间限制,超过屏幕像素的2.5倍则失效,并无法使用

举报

相关推荐

0 条评论