美文网首页
2.OpenGL的渲染结构与iOS离屏渲染

2.OpenGL的渲染结构与iOS离屏渲染

作者: 脩脩脩 | 来源:发表于2020-07-13 15:51 被阅读0次

一、渲染结构

OpenGL的渲染结构

OpenGL 渲染架构
Client:是指常见的iOS代码和OpenGL API方法,这部分是在CPU中运行
Server:是指OpenGL底层的渲染等处理,是运行在GPU中的
attribute属性, 直接用于顶点着色器, 不能直接传递到片元着色器, 通过GLSL代码间接传递到片元着色器。
Uniform 值(只是一个通道, 可传矩阵,可传单个值), 可直接传递到片元着色器和顶点着色器。
Vertex Shader: 顶点着色器 (可编程)
**Primitive Assembly **(图元装配 也叫光栅化): 顶点着色器 -> 光栅化(过程开发者是不可干预的) -> Fragment Shader, 只能编程Vertex Shader 和 Fragment Shader。
Fragment Shader:片元着色器(可编程)
TexTure Data:纹理数据 -> 顶点着色器,片元着色器
渲染一个图形: 比如渲染一个正方形 如果是渲染为蓝色 那么可以直接使用颜色去处理, 不用使用纹理, 要填充图片的话, 才需要使用到纹理。

OpenGL 为什么能够跨平台有一个很重要的原因是因为OpenGL是没有自己的窗口系统的, 每个平台需要使用OpenGL需要配合OpenGL集成一个自己的窗口系统。

iOS下的渲染架构

iOS下的渲染架构 iOS下的渲染架构

Core Animation: 本质上可以理解为一个复合引擎,主要职责包含:渲染,构建和实现动画。

二、离屏渲染

老生常谈的离屏渲染,无非就是cornerRadius,masksToBounds = YES, 我们来探究一下引起离屏渲染的真正因素。

先来一段简单的代码。


    UIButton *btn1 = [[UIButton alloc] initWithFrame:CGRectMake(100, 50, 100, 100)];
    btn1.layer.cornerRadius = 50;
    [btn1 setImage:[UIImage imageNamed:@"Popup_new1"] forState:UIControlStateNormal];
    btn1.clipsToBounds = YES;
    [self.view addSubview:btn1];

    UIButton *btn2 = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 100, 100)];
    btn2.layer.cornerRadius = 50;
    [btn2 setBackgroundColor:UIColor.redColor];
    btn2.clipsToBounds = YES;
    [self.view addSubview:btn2];

    UIImageView *imgView1 = [[UIImageView alloc] initWithFrame:CGRectMake(100, 400, 100, 100)];
    imgView1.image = [UIImage imageNamed: @"Popup_new1"];
    imgView1.layer.cornerRadius = 50;
    imgView1.layer.masksToBounds = YES;
    imgView1.backgroundColor = [UIColor redColor];
    [self.view addSubview:imgView1];

    UIImageView *imgView3 = [[UIImageView alloc] initWithFrame:CGRectMake(100, 550 , 100, 100)];
    imgView3.image = [UIImage imageNamed: @"Popup_new1"];
    imgView3.layer.cornerRadius = 50;
    imgView3.layer.masksToBounds = YES;
    [self.view addSubview:imgView3];

运行结果


image.png

以上现象说明了什么。

设置了cornerRadius和masksToBounds = YES 不一定会造成离屏渲染.

图片正常渲染,没有离屏的时候 流程是 APP -> 帧缓存区 -> 显示到界面上
离屏渲染: APP -> 离屏缓存区 -> 帧缓存区 -> 显示

为什么单独只设置了背景色或者图片的时候不会离屏,一般情况下 GPU渲染都会遵循画家算法,由远至近,一层一层的渲染,渲染完一个张后帧缓存区的数据会清空。

画家算法渲染图片
我们在切圆角的时候, 此时是只有一个图层,渲染好这张图片直接切了显示到界面上就可以了。
如果有多张图层的时候,先渲染好的图层需要等待其他的图层都渲染完成 ,如果不另外保存起来,那么之前的数据都清空了,那么久没有办法去处理圆角了。这个就叫离屏渲染,需要多开辟一个离屏缓存区,用于存放渲染后的数据再统一处理。

比较UIButton 和UIImageView
iOS的button setImage 是添加了一个imgaeView的,所以就有两个图层,所以在切button的圆角时 会造成离屏渲染,而如果只切button中的imageView圆角,是不会的,大家可以自己试一试。

cornerRadius+masksToBounds 只有在设置了content且背景不是透明时,才会出现离屏渲染。

三、iOS下常用圆角处理方案

方案一

imageView.clipsToBounds = YES;
imageVieiw.layer.cornerRadius = 4.0;

方案二

- (UIImage *)roundedCornerImageWithCornerRadius: (CGFloat)cornerRadius {
    CGFloat w = self.size.width;
    CGFloat h = self.size.height;
    CGFloat scale = [UIScreen mainScreen].scale;

    if (cornerRadius < 0) {
        cornerRadius = 0;
    } else if (cornerRadius > MIN(w, h)) {
        cornerRadius = MIN(w, h) / 2.;
    }
    UIImage *image = nil;
    CGRect imageFrame = CGRectMake(0.0, 0.0, w, h);
    UIGraphicsBeginImageContextWithOptions(self.size, NO, scale);
    [[UIBezierPath bezierPathWithRoundedRect:imageFrame cornerRadius:cornerRadius] addClip];
    [self drawInRect:imageFrame];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

方案三

- (void)addMaskToBounds: (CGRect)maskBounds cornerRadius:(CGFloat)cornerRadius {
    CGFloat w = maskBounds.size.width;
    CGFloat h = maskBounds.size.height;
    CGSize size = maskBounds.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    CGRect imageRect = CGRectMake(0, 0, w, h);

    if (cornerRadius < 0) {
        cornerRadius = 0;
    } else if (cornerRadius > MIN(w, h)) {
        cornerRadius = MIN(w, h) / 2.;
    }
    UIImage *image = nil;
    UIGraphicsBeginImageContextWithOptions(self.size, NO, scale);
    [[UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:cornerRadius] addClip];
    [image drawInRect:imageRect];
    self.roundImage = UIGraphicsGetImageFromCurrentImageContext();
    self.image = self.roundImage;
    UIGraphicsEndImageContext();
}

常见的触发离屏渲染的几种情况

  1. 使⽤了 mask 的 layer (layer.mask)
  2. 需要进⾏裁剪的 layer (layer.masksToBounds / view.clipsToBounds)
  3. 设置了组透明度为 YES,并且透明度不为 1 的 layer (layer.allowsGroupOpacity/layer.opacity)
  4. 添加了投影的 layer (layer.shadow*)
  5. 采⽤了光栅化的 layer (layer.shouldRasterize)
  6. 绘制了⽂字的 layer (UILabel, CATextLayer, Core Text 等)

相关文章

  • 2.OpenGL的渲染结构与iOS离屏渲染

    一、渲染结构 OpenGL的渲染结构 是指常见的iOS代码和OpenGL API方法,这部分是在CPU中运行 :是...

  • iOS离屏渲染

    iOS-离屏渲染详解关于iOS离屏渲染的深入研究关于离屏渲染这两片文章分析的很详细。 渲染过程 根据渲染流水线示意...

  • 三、iOS离屏渲染

    iOS离屏渲染 圆角不一定会造成离屏渲染 GPU屏幕渲染方式 On-Screen Rendering 当前屏幕渲染...

  • iOS离屏渲染的检测和优化

    在iOS离屏渲染介绍了离屏渲染的逻辑和原理,我们知道离屏渲染对于性能会有较大的消耗,那么开发中怎么避免产生离屏渲染...

  • 四、离屏渲染

    离屏渲染与正常渲染 屏幕上最终显示的数据有两种加载流程 正常渲染加载流程 离屏渲染加载流程离屏渲染与正常渲染 常⻅...

  • iOS圆角的离屏渲染,你真的弄明白了吗

    iOS圆角的离屏渲染,你真的弄明白了吗iOS圆角的离屏渲染,你真的弄明白了吗

  • iOS离屏渲染解析

    iOS离屏渲染解析

  • iOS-离屏渲染探索

    iOS项目性能优化时,不得不提到离屏渲染,为了提升性能,我们要求尽量减少离屏渲染的发生。 那,什么是离屏渲染?离屏...

  • iOS离屏渲染相关值得看的博客

    博客链接 iOS离屏渲染优化 绘制像素到屏幕上 关于iOS离屏渲染的深入研究 https://texturegro...

  • 离屏渲染

    离屏渲染是在iOS开发过程中脱离不了的话题,那么什么是离屏渲染以及哪些情况会导致离屏渲染呢?以及离谱渲染有哪些优势...

网友评论

      本文标题:2.OpenGL的渲染结构与iOS离屏渲染

      本文链接:https://www.haomeiwen.com/subject/jppacktx.html