iOS离屏渲染解析

离屏渲染

我们都知道一般情况下离屏渲染是犹豫设置了圆角触发的。触发离屏渲染真的只需要设置圆角么?下来我们通过案例分析来探讨下离屏渲染需要哪些条件?和普通渲染又有什么不同呢。

一、离屏渲染和正常渲染有什么区别?

首先,我们来了解一下几个名词。
1.On-Screen Rendering (当前屏幕渲染)
指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区进行.

2.Off-Screen Rendering (离屏渲染)
指的是在GPU在当前屏幕缓冲区以外开辟一个缓冲区进行渲染操作.

3.Frame Buffer (帧缓冲区)

4.OffScreenBuffer (离屏缓冲区)

  1. VSync(垂直同步信号)
    显示器显示出来的图像是经过 CRT电子枪逐行扫描,呈现一帧一帧画面的。为了防止图形撕裂,当一帧画面绘制完成后,电子枪回复到原位,准备画下一帧前,显示器会发出一个垂直同步信号。表示这一帧已经显示在显示器上,将原来的帧缓冲区清空,然后帧缓冲区加载下一帧图片。

离屏渲染就是比正常渲染多出来一个 OffScreen Rendering的过程,。当使用圆角,阴影,遮罩的时候,图层属性的混合体被指定为在未预合成之前(下一个VSync信号开始前)不能直接在屏幕中绘制,所以就需要屏幕外渲染。

二、哪些操作会触发 离屏渲染?

我们先说结论,再通过部分案例去验证。通过官方资料可以知道一下情况会出发离屏渲染。

1.shouldRasterize(光栅化): 将图转化为一个个栅格组成的图象。 光栅化特点:每个元素对应帧缓冲区中的一像素。shouldRasterize = YES在其它属性触发离屏渲染的同时,会将光栅化后的内容缓存起来,如果对应的layer或者 sublayers没有发生改变,在下一帧的时候可以直接复用,从而减少渲染的频率.
需要注意:

①如果layer 不能被复用,没有必要开启光栅化。
②如果layer不是静态,频繁被修改,比如在动画中,开始反而影响效率
③缓存内容时间限制,100ms内没被使用,自动丢弃
④缓存空间有限,最大不超过屏幕的2.5倍

2.masks(遮罩)
mask是layer的一个属性.

/ A layer whose alpha channel is used as a mask to select between the
 * layer's background and the result of compositing the layer's
 * contents with its filtered background. Defaults to nil. When used as
 * a mask the layer's `compositingFilter' and `backgroundFilters'
 * properties are ignored. When setting the mask to a new layer, the
 * new layer must have a nil superlayer, otherwise the behavior is
 * undefined. Nested masks (mask layers with their own masks) are
 * unsupported. */

@property(nullable, strong) CALayer *mask;

当透明度改变的时候,这个 mask 就是覆盖上去的那个阴影.该层的layer的alpha决定了多少层背景跟内容通过并显示,完全,或者部分不透明的像素允许潜在的内容 通过并显示.
默认是nil,当配置一个 遮罩的时候,记得设置 遮罩的大小,位置.已确保跟盖图层对齐.(这是官方文档说的 如果不对齐会怎样.you can try. 我试过是只能显示对齐的那一部分.)
如果你想给这个属性赋值,前提是必须没有 superLayer,如果有superLayer,这个行为则是无效的.

3.shadows(阴影)
4.edge antialiasing(抗锯齿)

layer.allowsEdgeAntialiasing = YES;

5.复杂形状设置圆角等
6.渐变
7.Text(UILabel, CATextLayer, Core Text, etc)...

三、如何检测离屏渲染

模拟器的 debug -> 选取 color Offscreen-Rendered.

image.png


例如下图黄色部分就发生了离屏渲染。


image.png

四、如何处理离屏渲染问题

1、只设置单层内容的圆角和剪切。
例如对UIButton添加圆角和剪切,会出发离屏渲染。
但是如果只针对button中的imageview添加,就不会触发离屏渲染。

// 设置圆角
button.imageView.layer.cornerRadius = 24;
// 设置裁剪
button.imageView.clipsToBounds = YES;

2、使用UIBezierPath通过上下文,重绘图片及边框圆角等。
3、mask遮罩(熟悉VVeboTableView的都知道,作者通过使用一个内部圆形镂空的图片来覆盖在原图上,以达到看似被裁剪的效果)

你可能感兴趣的:(iOS离屏渲染解析)