离屏渲染概述

news2024/12/12 18:27:48

我们知道,图像的处理基本都是在GPU中进行,然后GPU将渲染的结果放入当前渲染屏幕的帧缓冲区中,视频控制器取出里面的内容,在屏幕上进行显示。那么有没有什么情况,会因为某些限制,GPU无法将全部的渲染结果直接写入帧缓冲区呢?

离屏渲染

因为某些原因,比如阴影、遮罩等,GPU无法将渲染结果直接写入当前渲染屏幕的帧缓冲区中,而是需要在当前屏幕帧缓冲区以外新开辟一个帧缓冲区进行渲染操作,这个过程叫做离屏渲染。

我们先来看看layer的结构:

一旦我们 为contents设置了内容 ,无论是图片、绘制内容、有图像信息的子视图等,再加上圆角+裁剪,就会触发离屏渲染。而如果contents中没有内容,加上圆角+裁剪也不会触发离屏渲染。

也就是说,当layer的contens中有东西(图片,色彩等)时, GPU为了将所有该绘画的绘画完了,再去为这个“结果”添加阴影或圆角,那么就需要离屏渲染存储layer。也就是说:阴影的本体(layer和其子layer)都还没有被组合到一起,怎么可能在第一步就画出只有完成最后一步之后才能知道的形状呢?这样一来又只能另外申请一块内存,把本体内容都先画好。

下面我们一一探究离屏渲染是否触发:

shouldRasterize 光栅化

我们使用下面的demo进行测试:

import UIKit

class ViewController: UIViewController {
    
    lazy var imageView:UIImageView = {
        let imageView = UIImageView(frame: CGRect(x:80,y:200,width:150,height:180))
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(imageView)
        self.imageView.image = UIImage(named: "1")
        imageView.layer.shouldRasterize = true//光栅化
    }


}

 然后进行如下操作观察是否有离屏渲染:

这时你会发现有光栅化会触发离屏渲染 。

shouldRasterize开启后,会将layer作为位图保存下来,下次直接与其他内容进行混合。这个保存的位置就是OffscreenBuffer中。这样下次需要再次渲染的时候,就可以直接拿来使用了。

shouldRasterize使用建议:

  • layer不复用,没必要打开shouldRasterize
  • layer不是静态的,也就是说要频繁的进行修改,没必要使用shouldRasterize
  • 离屏渲染缓存内容有100ms时间限制,超过该时间的内容会被丢弃,进而无法复用
  • 离屏渲染空间是屏幕像素的2.5倍,如果超过也无法复用

遮罩Mask

添加遮罩的代码如下:

        let layer = CALayer()
        layer.frame = imageView.bounds
        layer.backgroundColor = UIColor.red.cgColor
        self.imageView.layer.mask = layer//设置遮罩

测试发现,会发生离屏渲染

阴影

阴影代码如下:

        imageView.layer.shadowColor = UIColor.red.cgColor//添加阴影
        imageView.layer.shadowOffset = CGSize(width: 20, height: 20)
        imageView.layer.shadowOpacity = 0.5
        imageView.layer.shadowRadius = 5

测试发现会发生离屏渲染。

抗锯齿

代码如下:

        self.imageView.layer.allowsEdgeAntialiasing = true

测试发现,不会发生离屏渲染

透明度

测试代码如下:

        let view = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
        view.backgroundColor = .red
        self.imageView.addSubview(view)
        self.imageView.alpha = 0.5
        self.imageView.layer.allowsGroupOpacity = true

测试结果发现:会发生离屏渲染

但是注意,如果allowsGroupOpacity设置成false,也就是不允许子视图与自己的透明度一样,这样不会触发离屏渲染,imageView的透明度(alpha)设置成1也不会触发离屏渲染。

圆角

测试代码如下:

        self.imageView.backgroundColor = .red
        self.imageView.layer.cornerRadius = 20
        self.imageView.clipsToBounds = true

测试发现,圆角处会发生离屏渲染

注意:然后你再创建一个label,同样操作测试:

       self.view.addSubview(label)
        self.label.backgroundColor = .red
        self.label.layer.cornerRadius = 20
        self.label.clipsToBounds  = true

你会发现:label的圆角处不会触发离屏渲染。这是为什么?

这是因为我们设置imageView的backgroundColor时,设置的是layer的backgroundColor,但是,设置label的backgroundColor时,设置的是layer的contents里的backgroundColor,我们用下面的代码验证:

 self.imageView.backgroundColor = .red
        self.imageView.layer.backgroundColor = UIColor.green.cgColor
        self.imageView.layer.cornerRadius = 20
        self.imageView.clipsToBounds = true
        
        self.view.addSubview(label)
        self.label.backgroundColor = .red
        self.label.layer.backgroundColor = UIColor.green.cgColor
        self.label.layer.cornerRadius = 20
        self.label.clipsToBounds  = true

测试发现:imageView的背景颜色是green,而label的背景颜色却是red,这也验证了这一点,我们改变label中layer里的backgroundColor为绿色,但是contents中却是红色,在layer层中contents在上层,会覆盖掉下层颜色,所以还是红色。

设置圆角时,只会设置backgroundColor和border,要触发离屏渲染,我们需要操作contents。

离屏渲染的劣势:

离屏渲染增大了系统的负担,会形象App性能。主要表现在以下几个方面:

  • 离屏渲染需要额外的存储空间,渲染空间大小的上限是2.5倍的屏幕像素大小,超过无法使用离屏渲染
  • 容易掉帧:一旦因为离屏渲染导致最终存入帧缓存区的时候,已经超过了16.67ms,则会出现掉帧的情况,造成卡顿

优化:

  • 贝塞尔曲线绘制圆角
  • 如果产品设计圆角+阴影的卡片,可以使用切图实现圆角+阴影,避免触发离屏渲染,这也是最优解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2258360.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探索 Python 应用的分层依赖:解决 Linux 环境中的 libvirt-python 安装问题

探索 Python 应用的分层依赖:解决 Linux 环境中的 libvirt-python 安装问题 背景Python 版本升级 问题描述原因分析与解决方案 Python 应用的分层依赖:安装与部署的视角libvirt-python的分层依赖尝试的解决方案 使用编译好的 .whl 文件"嫁接"整…

vmware vsphere5---部署vCSA(VMware vCenter Server)附带第二阶段安装报错解决方案

声明 因为这份文档我是边做边写的,遇到问题重新装了好几次所以IP会很乱 ESXI主机为192.168.20.10 VCSA为192.168.20.7,后台为192.168.20.7:5480 后期请自行对应,后面的192.168.20.57请对应192.168.20.7,或根据自己的来 第一阶段…

Unity3D下采集camera场景并推送RTMP服务实现毫秒级延迟直播

技术背景 好多开发者,希望我们能够分享下如何实现Unity下的camera场景采集并推送rtmp服务,然后低延迟播放出来。简单来说,在Unity 中实现采集 Camera 场景并推送RTMP的话,先是获取 Camera 场景数据,通过创建 RenderTex…

指令周期流程图

例题一 例题二 例题三

使用C#通过ColorMatrix对象为图像重新着色

此示例产生了一些令人印象深刻的结果,但实际上非常简单。 它使用其他几个示例演示的 ImageAttribute 技术来快速操作图像的颜色。 下面的AdjustColor方法启动图像着色的过程。 // Adjust the images colors. private Image AdjustColor(Image image) {// Make the …

SQL 在线格式化 - 加菲工具

SQL 在线格式化 打开网站 加菲工具 选择“SQL 在线格式化” 或者直接访问 https://www.orcc.online/tools/sql 输入sql,点击上方的格式化按钮即可 输入框得到格式化后的sql结果

AI作图效率高,亲测ToDesk、顺网云、青椒云多款云电脑AIGC实践创作

一、引言 随着人工智能生成内容(AIGC)的兴起,越来越多的创作者开始探索高效的文字处理和AI绘图方式,而云电脑也正成为AIGC创作中的重要工具。相比于传统的本地硬件,云电脑在AIGC场景中展现出了显著的优势,…

【密码学】SM4算法

一、 SM4算法简介 SM4算法是中国国家密码管理局于2012发布的一种分组密码算法,其官方名称为SMS4(SMS4.0),相关标准为GM/T 0002-2012《SM4分组密码算法》。SM4算法的分组长度和密钥长度均为128比特,采用非平衡Feistel结构。采用32…

Proteus(8.15)仿真下载安装过程(附详细安装过程图)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Proteus是什么? 二、下载链接 三、下安装步骤 1.解压,有键管理员运行 2.点击Next,进行下一步 3.勾选I accept…&#…

【工业机器视觉】基于深度学习的水表盘读数识别(4-训练与预测)

【工业机器视觉】基于深度学习的仪表盘识读(读数识别)(3)-CSDN博客 训练与预测 Ultralytics YOLO指的是由Ultralytics公司开发的一系列基于YOLO(You Only Look Once)架构的目标检测算法。YOLO是一种实时目标检测系统,它…

AlphaPose、yolov8Pose、RTMPose进行对比

一、Alphapose 参考: https://blog.csdn.net/m0_45850873/article/details/123939849

MongoDB-ObjectID 生成器

前言 MongoDB中一个非常关键的概念就是 ObjectID,它是 MongoDB 中每个文档的默认唯一标识符。了解 ObjectID 的生成机制不仅有助于开发人员优化数据库性能,还能帮助更好地理解 MongoDB 的设计理念。 什么是 MongoDB ObjectID? 在 MongoDB …

ARM学习(36)静态扫描规则学习以及工具使用

笔者来学习了解一下静态扫描以及其规则,并且亲身是实践一下对arm 架构的代码进行扫描。 1、静态扫描认识 静态扫描:对代码源文件按照一定的规则进行扫描,来发现一些潜在的问题或者风险,因为不涉及代码运行,所以其一般只是发现一些规范或则一些质量问题,当然这些可能存在潜…

从 Zuul 迁移到 Spring Cloud Gateway:一步步实现服务网关的升级

从 Zuul 迁移到 Spring Cloud Gateway:一步步实现服务网关的升级 迁移前的准备工作迁移步骤详解第一步:查看源码第二步:启动类迁移第三步:引入 Gateway 依赖第四步 编写bootstrap.yaml第五步:替换路由配置第六步&#…

centos部署SkyWalking并在springcloud项目中用法举例

文章目录 场景SkyWalking介绍部署部署Storage [单机版Elasticsearch]部署SkyWalking OAP [下载地址](https://skywalking.apache.org/downloads/#SkyWalkingAPM)部署SkyWalking Java Agent springCloud 使用举例 场景 SkyWalking是应用性能监控平台,可用于分布式系统…

如何借助5G网关实现油罐车安全在线监测

油罐车是常见的特种运输车辆,用以运送各种汽油、柴油、原油等油品,运输危险系数大,而且由于油罐车需要经常行驶在城区道路,为城市各个加油站点、企业工厂运输补充所需油料,因此也是危化品运输车辆的重点监测和管控对象…

【总结·反思·汇报·思考02】裸辞后,我的一些感想和感悟。

Hello,大家好! 首先,我需要向大家道个歉,对不起!因为最近发生了一些事情,博客文章一直没有更新。(90度鞠躬道歉) 那么,最近到底发生了什么呢?相信大家已经从…

李宏毅机器学习-局部最小值与鞍点

一、Optimization Fails because …… 1. 问题 在optimization时,training的loss不会再下降,但是我们对loss并不满意。不管我们怎么更新参数,loss都不会掉下来。 2. 原因:critical point(gra…

day10性能测试(2)——Jmeter安装环境+线程组+Jmeter参数化

【没有所谓的运气🍬,只有绝对的努力✊】 目录 1、LoadRunner vs Jmeter 1.1 LoadRunner 1.2 Jmeter 1.3 对比小结 2、Jmeter 环境安装 2.1 安装jdk 2.2 安装Jmeter 2.3 小结 3、Jmeter 文件目录结构 4、Jmeter默认配置修改 5、Jmeter元件、组…

STM32软件IIC驱动TCA9548A多路测量AHT10

STM32软件IIC驱动TCA9548多路测量AHT10 TCA9548AAHT10代码逻辑代码展示现象总结 TCA9548A TCA9548A 有八个可通过 I2C 总线控制的双向转换开关,SCL/SDA 上行对扩展到八个下行对,或者通道,适用于系统中存在I2C目标地址冲突的情况。8路双向转换…