• 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倍后,也不能继续复用了

  • 相关阅读:
    使用Sharepoint Designer 无法打开站点提示错误403 forbidden
    英文Windows系统打开带中文TXT出现乱码
    Linux查看MegaSAS raid卡缓存策略
    PostgreSQL基础CRUD
    PostgreSQL安装(on Windows 10)
    Node.js安装(on Windows 10)
    Spring Data JPA:建立实体类
    Java:类加载
    Spring Data JPA:关联关系(外键)
    MySQL系统化知识概要
  • 原文地址:https://www.cnblogs.com/zhangzhang-y/p/13263728.html
Copyright © 2020-2023  润新知