引言:设置圆角一定会出现离屏渲染吗?
我们先看下面的四种情况,有哪些会出现离屏渲染呢
我们运行模拟器,然后打开模拟器的Off-screen Rendered,屏幕显示黄色则表示出现离屏渲染。这里我们看到了1,3出现了离屏渲染。在解释这个问题之前我们先往下看。
一、离屏渲染的原理和影响
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)
3. 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倍则失效,并无法使用