iOS离屏渲染

2020-07-07  本文已影响0人  东旭39

iOS-离屏渲染详解
关于iOS离屏渲染的深入研究
关于离屏渲染这两片文章分析的很详细。

渲染过程

ios-core-animation-pipeline-steps.png

根据渲染流水线示意图,渲染操作的过程CoreAnimation->Render Server->OpenGL/Metal->GPU->显示。
Render Server会遵循“画家算法”,画家算法先画远景,然后画近景。Render Server根据sublayer添加的顺序按次序输出到frame buffer,显示到屏幕上的时候,后一层覆盖前一层,就能得到最终的显示结果,已经完成显示的数据将会被丢弃。
由于frame buffer中的渲染数据完成显示,会被GPU丢弃,如果我们对它修改就需要保存在新的一个内存空间中,这个新开辟的内存空间就会造成离屏渲染

离屏渲染既然会影响性能为什么还要用?

  1. 特殊效果,需要使⽤额外的offscreen Buffer 保存中间状态,不得不使⽤离屏渲染 -> 系统⾃动触发. 圆 ⻆,阴影;
  2. 效率的优势: 既然效果会多次屏幕-> 提前渲染 offscreenBuffer -> 复⽤⽬的‘

缺点:

在iOS中会触发离屏渲染的操作

  1. shouldRasterize的使用建议

    • 如果layer不能被复用,没有必要开启光栅化
    • 如果layer不是静态的,需要被频繁修改,比如layer有动画,那么开启光栅化反而影响效率
    • 离屏渲染缓存有时间限制,缓存内容100ms没有被使用,那么缓存内容就会被丢弃。
    • 离屏渲染缓存空间有限,超过屏幕像素点2.5被也会失效。
  2. layer.mask 遮罩
    遮罩操作需要进行多次OpenGL es的混合操作,mask+整个layer = 需要的view。由于GPU不能一次完成,因为遮罩会用到OpenGL es的混合,首先需要绘制layer图层,获取mask的图片转换成纹理数据,然后再最后将mask与layer混合成我需要的蒙板视图。
    而frame buffer无法对已经处理好的数据进行修改(16.7ms完成一次遍历)。所以利用离屏缓冲区可以长效保存的特性,将mask和layer存入离屏缓冲区然后进行混合操作。

  3. layer.cornerRadius 会设置background和border的圆角,不会设置image的layer.content的圆角,需要设置layer.masksToBounds=YES才会成功。

Setting the radius to a value greater than 0.0 causes the layer to begin drawing rounded corners on its background. By default, the corner radius does not apply to the image in the layer’s contents property; it applies only to the background color and border of the layer. However, setting the masksToBounds property to true causes the content to be clipped to the rounded corners. ——Apple 官方文档

离屏渲染

//1.按钮存在背景图片
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.按钮不存在背景图片
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;

//3.UIImageView 设置了图片+背景色;
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 只设置了图片,无背景色;
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"];

`
打开离屏渲染效果


offscreen.png

设置圆角的时候,只有在view中有图片和背景色,设置圆角会造成离屏渲染,而单个背景色和单个图片的时候不会触发离屏渲染。

圆角的处理

上一篇下一篇

猜你喜欢

热点阅读