離屏渲染的理解

什么是離屏渲染

Off-Screen Rendering意為離屏渲染,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作

為什么需要離屏渲染

因?yàn)樵趲彌_區(qū)渲染一個(gè)視圖到屏幕中就拋棄的機(jī)制.所以當(dāng)我們有多組視圖需要組合隨后統(tǒng)一處理的時(shí)候.需要在屏緩沖區(qū)額外開辟一個(gè)離屏的緩沖區(qū)去記錄這些視圖.隨后統(tǒng)一處理.最后渲染顯示出來

離屏渲染.png

怎么產(chǎn)生離屏渲染

我們首先分析圓角產(chǎn)生離屏渲染的情況:

回顧一下.當(dāng)我們給一個(gè)視圖添加cornerRadius時(shí).是給哪些視圖添加了圓角?

蘋果官方的解答是:

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 YES causes the content to be clipped to the rounded corners.The default value of this property is 0.0.

即背景視圖以及邊框等視圖,不包含contents視圖.所以當(dāng)我們只設(shè)置cornerRadius時(shí).不設(shè)置masksToBounds為YES.視圖視覺上還是沒產(chǎn)生圓角

image.png

隨后我們對以下四種情況分別做圓角處理
a.按鈕視圖設(shè)置圖片.并且設(shè)置圓角cornerRadius和裁剪masksToBounds.會(huì)產(chǎn)生離屏渲染
b.按鈕視圖不設(shè)置圖片.設(shè)置圓角cornerRadius和裁剪masksToBounds.不會(huì)產(chǎn)生離屏渲染
c.圖片視圖不設(shè)置背景色.設(shè)置圓角cornerRadius和裁剪masksToBounds.不會(huì)產(chǎn)生離屏渲染
d.圖片視圖設(shè)置背景色.設(shè)置圓角cornerRadius和裁剪masksToBounds.會(huì)產(chǎn)生離屏渲染

相關(guān)代碼如下:

    //設(shè)置圖片會(huì)產(chǎn)生離屏渲染
    UIButton * btn1 = [UIButton buttonWithType:(UIButtonTypeCustom)];
    btn1.frame = CGRectMake(100, 30, 100, 100);
    [btn1 setImage:[UIImage imageNamed:@"WX20201127-92813"] forState:UIControlStateNormal];
    [self.view addSubview:btn1];
    btn1.layer.cornerRadius = 50;
    btn1.layer.masksToBounds = YES;

    //只設(shè)置背景色不會(huì)產(chǎn)生離屏渲染
    UIButton * btn2 = [UIButton buttonWithType:(UIButtonTypeCustom)];
    btn2.frame = CGRectMake(100, 150, 100, 100);
    btn2.backgroundColor = UIColor.grayColor;
    [self.view addSubview:btn2];
    btn2.layer.cornerRadius = 50;
    btn2.layer.masksToBounds = YES;
    
    //對于圖片來說.設(shè)置背景色以及圖片就會(huì)產(chǎn)生離屏渲染.不設(shè)置就不會(huì)
    UIImageView * img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"WX20201127-92813"]];
    img1.frame = CGRectMake(100, 270, 100, 100);
    img1.backgroundColor = UIColor.blueColor;
    img1.layer.cornerRadius = 50;
    img1.layer.masksToBounds = YES;
    [self.view addSubview:img1];
    

    UIImageView * img2 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"WX20201127-92813"]];
    img2.frame = CGRectMake(100, 390, 100, 100);
    img2.layer.cornerRadius = 50;
    img2.layer.masksToBounds = YES;
    [self.view addSubview:img2];

效果如下:


image

那什么情況下會(huì)產(chǎn)生離屏渲染呢?
我們得出的表象結(jié)論是:

1.按鈕添加圖片以后做圓角處理
2.圖片視圖添加背景色和圖片以后做圓角處理

接下來.我們將img2進(jìn)行改進(jìn): 給tempView不加背景色不會(huì)產(chǎn)生離屏渲染.給tempView添加背景色還是會(huì)產(chǎn)生離屏渲染

    UIImageView * img3 = [[UIImageView alloc]init];
    img3.frame = CGRectMake(100, 510, 100, 100);
    img3.layer.cornerRadius = 50;
    img3.layer.masksToBounds = YES;
    [self.view addSubview:img3];
    
    UIView *tempView = [[UIView alloc]init];
    tempView.backgroundColor = UIColor.redColor;
    tempView.frame = img3.bounds;
    [img3 addSubview:tempView];
讀取緩存區(qū).png

由此我們可以知道:當(dāng)我們需要對多個(gè)圖層進(jìn)行組合處理時(shí)就需要使用到離屏渲染技術(shù).將多個(gè)圖層組合渲染完畢以后放到幀緩沖區(qū).顯示到屏幕中

需要注意的是.以上是組合.而不是疊加.

那么我們平時(shí)使用的視圖有哪些是組合.并且需要做離屏渲染的呢?

2.mask遮罩
3.光柵化
4.組合視圖設(shè)置透明度
5.陰影
6.漸變
7.繪制文字
8.系統(tǒng)毛玻璃效果

如何避免離屏渲染?

1.針對圓角的離屏渲染的情況.我們可以通過四種方案.
a.使用一個(gè)鏤空圓角視圖蓋在上面
b.使用YYImage里面的圓角方法
C.通過CALayerUIBezierPath結(jié)合使用的

        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        UIBezierPath.init(roundedRect: imgRect, cornerRadius: self.layer.cornerRadius).addClip()
        self.image?.draw(in: imgRect)
        self.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

2.如果視圖不能被復(fù)用.并且不是靜態(tài).需要被頻繁修改的情況不建議開啟光柵化.因?yàn)檫@樣會(huì)開啟離屏渲染會(huì)影響效率
3.盡量少使用或不使用透明度
4.異步繪制.減少圖層

題外話:
1.離屏渲染緩存內(nèi)容有時(shí)間限制.緩存內(nèi)容100ms內(nèi)容如果沒有被使用.那么它就會(huì)丟棄.無法進(jìn)行復(fù)用
2.離屏渲染緩存空間有限.超過2.5倍屏幕像素大小的話.也會(huì)失效.且無法進(jìn)行復(fù)用了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. OpenGL中,GPU屏幕渲染有以下兩種方式 On-Screen Rendering 當(dāng)前屏幕渲染: 是GP...
    MrDemon_閱讀 389評論 0 0
  • 屏幕顯示圖像的原理: 高中物理應(yīng)該學(xué)過顯示器是如何顯示圖像的:需要顯示的圖像經(jīng)過CRT電子槍以極快的速度一行一行的...
    青火閱讀 27,887評論 18 104
  • 圓角不一定會(huì)離屏渲染 離屏渲染的原理 當(dāng)頁面需要進(jìn)行額外的渲染和合并,需要將layer分次渲染,存到離屏緩沖區(qū)(o...
    CrazySnow閱讀 627評論 0 1
  • 什么是離屏渲染 當(dāng)圖層屬性的混合體被指定為在未預(yù)合成之前不能直接在屏幕中繪制時(shí),屏幕外渲染就被喚起了。屏幕外渲染并...
    澤澤伐木類閱讀 623評論 0 1
  • 離屏渲染定義 離屏渲染的流程如圖: GPU把渲染好的的內(nèi)容存放到離屏渲染緩沖區(qū)中,在離屏渲染緩沖區(qū)(Offscre...
    DSMars閱讀 190評論 0 0

友情鏈接更多精彩內(nèi)容