1、屏幕渲染
屏幕渲染分为常规渲染和离屏渲染。
常规渲染流程:App -> FrameBuffer -> Display
当系统绘制好需要展示的图形后,直接提交到帧缓存区,显示到屏幕上,然后立即抛弃掉原来帧缓存区里的内容,进行下一次的渲染。
离屏渲染流程:App -> OffScreen Buffer(进行计算合并等操作) -> FrameBuffer -> Display
当需要显示的内容不能一次性绘制的时候,需要一部分一部分的绘制,并提交到 OffScreen Buffer。全部绘制完成后再合并,最后把合成的内容提交到 frameBuffer 中,显示到屏幕。显然离屏渲染比常规渲染多了一步 ,即提交 OffScreen Buffer,合成计算。
2、离屏渲染的流程
1、渲染 Mask 纹理,保存到离屏缓存区。
2、计算 layer 纹理部分,保存到离屏缓存区。
3、在开辟的离屏渲染缓存区里,将 Mask 和 layer 内容混合计算渲染,最后在提交到 FrameBuffer -> 展示到屏幕上。
![](https://img.haomeiwen.com/i1742120/34cfe1d6b792c15c.png)
3、常见离屏渲染
1、layer 的 cornerRadius+maskToBounds,叠加图层才会触发。比如 UIImageView 同时设置背景颜色+图片。
2、shouldRasterize 光栅化
3、半透明视图混合
4、毛玻璃效果
5、绘制文字的 layer
注:检查离屏渲染方法
可以通过在模拟器上,Debug-> Color Off-Screen Rendered ,若其中出现黄色背景的,则为触发了离屏渲染。
4、常见离屏渲染示例
cornerRadius + masksToBounds
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:@"22.jpg"];
//结论:
img1.backgroundColor = [UIColor blueColor]; 这行代码打开注释,就会发现触发了离屏渲染,关闭,则没有触发。
也就是说 cornerRadius+masksToBound 并不是一定会引发离屏渲染。关键是要看有几层渲染数据。该示例中有以下需要渲染的数据 backgroundcolor、content(image、text等)。cornerRadius+masksToBound 只有在设置了content 且背景不是透明时,才会出现离屏渲染。如果一定要使用 cornerRadius+masksToBound 的方式裁切图片,不要设置 backgroundColor。
注:cornerRadius 并不是对 content(image) 有效,根据苹果官方解释:cornerRadius 的文档中明确说明对 cornerRadius 的设置只对 CALayer 的** backgroundColor 和 borderWidth、borderColor**起作用。
毛玻璃效果
如要实现一个毛玻璃效果,渲染的位图并不能直接给帧缓存区等待显示,而要经过模糊处理之后才能将最后的渲染数据 -> 帧缓冲区-> 显示。其流程如下:
渲染内容 -> 捕获内容 -> 水平模糊 -> 垂直模糊 -> 合成过程 -> 提交 FrameBuffer -> Display。
shadow 阴影
shadow 是一个矩形,是一个背景色,所以要在 layer 的下方。shadow 是根据 layer 而来,要根据 layer 确定自身的位置大小。
如果没有离屏渲染,根据画家算法,要先将 shadow 放入帧缓存区显示。但是 layer 没有,不可能先渲染 shadow。只能利用离屏渲染缓冲区,等待 shadow、layer 等渲染并合并完成后,再送入帧缓存区等待显示。
shouldRasterize 光栅化
根据官方文档,如果开启光栅化,会将 layer 最后的渲染,包括阴影、裁切等的最终效果变成位图放入离屏缓冲区,等待复用。但是
1、离屏缓冲区的大小不能超过屏幕的2.5倍,否则被释放;
2、layer 如果不是静态的(比如 imageview 的 image 、label 的 text 等会发生频繁改变),开启 shouldRasterize 离屏渲染会影响效率;
3、离屏缓冲区是有时间限制的,超过100ms如果没有被使用,也会被释放。
所以,使用 shouldRasterize 时:
如果 layer 不是静态的,不建议开启;
如果 layer 不能不能被复用,也不建议开启(cell 被复用,动画中的 layer 等);
超过100ms没有被复用,也不建议开启;
超出离屏渲染控件 屏幕像素的2.5倍,也不建议开启;
group opacity 组透明度
当有很多 sublayer 时候,并不是每渲染一层 sublayer 立刻显示。我们对靠后的大 sublayer 设置透明度,首先在离屏渲染区等待 layer 的全部 sublayer 完成后,再根据组透明度,计算新的颜色,进行颜色整合,最后提交帧缓冲区。如果 opacity 为1则不需要调整透明度。
masks
masklayer 作为遮罩,显示在其所在的大 layer 以及大 layer 的所有子 sublayer 之上。masklayer 可能也会带有透明度、形状。那么,我们必须在离屏渲染缓冲区内完成 Image 和 Mask 的裁切合并处理,才能将最终的 Masked Image -> 帧缓冲区显示。
网友评论