OpenGL 三

正式开始前,我们可以先看一下下面几段代码:

 1 //1.按钮存在背景图片 ==========》 触发了离屏渲染
 2     UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
 3     btn1.frame = CGRectMake(100, 30, 100, 100);
 4     btn1.layer.cornerRadius = 50;
 5     [self.view addSubview:btn1];
 6     
 7     [btn1 setImage:[UIImage imageNamed:@"btn.png"] forState:UIControlStateNormal];
 8     btn1.clipsToBounds = YES;
 9     
10     //2.按钮不存在背景图片
11     UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
12     btn2.frame = CGRectMake(100, 180, 100, 100);
13     btn2.layer.cornerRadius = 50;
14     btn2.backgroundColor = [UIColor blueColor];
15     [self.view addSubview:btn2];
16     btn2.clipsToBounds = YES;
17     
18     //3.UIImageView 设置了图片+背景色; ==========》 触发了离屏渲染
19     UIImageView *img1 = [[UIImageView alloc]init];
20     img1.frame = CGRectMake(100, 320, 100, 100);
21     img1.backgroundColor = [UIColor blueColor];
22     [self.view addSubview:img1];
23     img1.layer.cornerRadius = 50;
24     img1.layer.masksToBounds = YES;
25     img1.image = [UIImage imageNamed:@"btn.png"];
26     
27     //4.UIImageView 只设置了图片,无背景色;
28     UIImageView *img2 = [[UIImageView alloc]init];
29     img2.frame = CGRectMake(100, 480, 100, 100);
30     [self.view addSubview:img2];
31     img2.layer.cornerRadius = 50;
32     img2.layer.masksToBounds = YES;
33     img2.image = [UIImage imageNamed:@"btn.png"];

     //5.UIView 多个贴在 self.view 上

       UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 600, 100, 100)];

       view1.backgroundColor = [UIColor blackColor];

       view1.layer.cornerRadius = 50;

       view1.clipsToBounds = YES;

       [self.view addSubview:view1];

       UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(100, 600, 60, 60)];

       view2.backgroundColor = [UIColor whiteColor];

       view2.layer.cornerRadius = 30;

       view2.clipsToBounds = YES;

       [self.view addSubview:view2];

运行,开启模拟器的查看离屏渲染触发功能:可看到 1 和 3 两段代码触发了离屏渲染()。他们都开了圆角,却并没有都触发离屏渲染,这是为什么呢?

 

   

 一、渲染简图 - 普通 & 离屏

普通渲染:普通情况下,我们的APP的渲染流程是,CPU/GPU 合作,不断的将需要渲染的内容数据存到帧缓存区(Frame Buffer),显示则是不断地从帧缓存区取出数据进行显示。多个view  每个都独立 一层一层贴 在主view上。

 离屏渲染:触发离屏渲染时,数据不会直接存到帧缓存区,而是先放在 另外开辟了一块缓存区空间 --> 离屏缓存区(offscreen Buffer),在不断地将数据存到离屏缓存区,之后将几个图层进行合并叠加,然后通过帧缓存区,再进行显示。一个view上多个图层。

二、离屏渲染 

1)为什么离屏渲染呢?例子:我们要显示一个 button --> 背景粉色、有颗球的背景图、圆角4 -->  这些图层是不能一个个单独的显示在屏幕,需要三个叠加,那么叠加处理前 就要有个地方先存放它们 --> offscreen Buffer --> 三个都处理好了,然后一起叠加、处理 --> 到帧缓存区 --> 显示。 (这里的图层叠加并非是一层层独立 view 的叠加,而是它们三个在同一层layer上)

张图:

“不能单独的显示在屏幕”是设么意思呢?在脑海里想象一下,你想要做幅画,它要长成下面描述的样子,首先一层绿色的树背景、背景上有棵大树干、树根旁有只猫,最后要把这个图裁成圆形的。我们是不是要至少画三个元素(绿色、树、猫)合在一起才能呈现出这幅画,然后一剪刀将其裁成的圆。画纸便是我们的一层 view。“一张画纸上画多种元素” 区别于 “每张画纸画一种元素多张画纸叠加”。

你可能要说那他为什么非要触发离屏渲染呢?离屏渲染又要消耗我们的性能,我不可以直接一层一层的 view 摆放在屏幕上吗?当然可以,但这个的前提是你要向 UI 要张圆形的图片嘛,我们暂不考虑这个,没有现成的图的情况下我们是需要自己裁的。

2)离屏渲染为什么会引起性能问题呢?

  1、要额外存储空间,大量的离屏渲染会使内存压力会比较大

  2、offscreen Buffer --> frame Buffer 这个过程是需要一定时间的

  3、离屏缓存区的空间是有他的大小限制的:屏幕的2.5倍(像素点)

3)离屏渲染的大量使用,会造成性能问题,可能会引起掉帧卡顿现象,那么为什么要用离屏渲染呢?

  1、不得不使用:我们所需要的的一些特殊效果特效,并不能一次性一个图层就得到想要的结果的,必须要多个图层一起实现,不得不。

  2、效率:特殊效果的复用。多次出现的一个动画特效,渲染结果保存在离屏缓存区里面,用的时候直接取。

到这里,我们再考虑下为什么切圆角没有都触发离屏渲染呢

  图层只有一层时(一个颜色or一张背景图...),我们对其渲染切圆角后直接就可以将其显示在屏幕中了,不需要有另外的图片或者其他什么和他混在一起的效果图,那么何必将其放在离屏缓存区消耗空间呢。

三、触发离屏渲染的常见场景

1)系统自动触发:

  1、裁剪layer:例:切圆角 -- view.layer.masksToBounds = YES;(等同于 view.clipsToBounds = YES; )// 触发离屏渲染原因

  圆角效果的几点实现:

  a、按上面代码直接切

  b、贝塞尔曲线画圆角

  c、找UI要切好的图

  

  2、阴影

  3、高斯模糊

  4、带透明度的图层的重合: 重合部分的颜色是必须要混合计算的

苹果毛玻璃效果(高斯模糊)的渲染流程图:

例子:对一张图片进行模糊处理:

  渲染内容-Render Content(存offscreen Buffer) --> 抓取捕获图片内容-capture content(存) --> 垂直模糊-vertical blur(存) --> 水平模糊-horizonal blur(存) --> 合成compositiong Pass(四合一) --> 显示 

2)主动触发:我们在复用时

  光栅化:shouldRasterize --> When the value of this property is YES, the layer is rendered as a bitmap in its local coordinate space and then composited to the destination with any other content

  当设为YES时会开启离屏渲染。

shouldRasterize 光栅化使用建议:

  1、如果layer不能被复用,不要开启

  2、layer不是静态的,要时时变化频繁修改,开启离屏渲染反而影响效率

  3、离屏渲染缓存内容是有时间限制的,当存的内容在100ms内没有被复用,便会被清理掉,无法复用

  4、离屏渲染空间限制,2.5倍的屏幕,超过屏幕像素大小的2.5倍后,也不能继续复用了

原文地址:https://www.cnblogs.com/zhangzhang-y/p/13263728.html