Offscreen-Rendered

序言

本篇是记录笔者探索离屏渲染的笔记,学习离屏渲染如何引起、如何解决。同时,好好理解一下什么离屏渲染(Offscreen-rendered),什么是当屏渲染(Onscreen-Rendered)。了解GPU与CPU的一些小知识。

本篇主要一起来学习学习:

  • Color Offscreen-Rendered Yellow. Places a yellow overlay over content that is rendered offscreen.
  • Color Hits Green and Misses Red. Marks views in green or red. A view that is able to use a cached rasterization is marked in green.

基本概念

在OpenGL中,GPU屏幕渲染有以下两种方式:

  • Onscreen-Rendered:当前屏幕渲染,指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。
  • Offscreen-Rendered:即离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。

Offscreen-rendered缺点

与当前屏幕渲染相比,离屏渲染的代价是很高的,主要体现在两个方面:

  • 创建新缓冲区:要想进行离屏渲染,首先要创建一个新的缓冲区。
  • 上下文切换:离屏渲染的整个过程,需要多次切换上下文环境。先是从当前屏幕(On-Screen)切换到离屏(Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上又需要将上下文环境从离屏切换到当前屏幕。但是,上下文环境的切换是要付出很大代价的。

哪些可引起Offscreen-rendered

有以下方式可以引起离屏渲染:

  • shouldRasterize设置为YES
  • masks(遮罩)
  • shadows(阴影)
  • edge antialiasing(抗锯齿)
  • group opacity(不透明)
  • cornerRadius+clipToBounds/maskToBounds设置圆角
  • 重写drawRect交由CPU渲染

如何检测离屏渲染

在Instruments->Core Animation下,如下图,勾选上:

注意:要求在真机才可以的哦!

光栅化(shouldRasterize)

shouldRasterize = YES时,在其他属性触发离屏渲染的同时,会将光栅化后的内容缓存起来,以便在下一帧的时候可以直接复用。这会隐式地创建一个位图,各种阴影遮罩等效果也会保存到位图中并缓存起来,从而减少渲染的次数,提高一定的性能。

当我们设置了shaouldRasterize = YES后,我们就可以开启“Color Hits Green and Misses Red”来检查该场景下光栅化操作是否是一个好的选择。命中缓存则显示绿色,不命中缓存,则会显示为红色。

因此,我们要通过检测是否值得使用光栅化。比如,如果在设置为YES后,在快速滚动的时候,绿色较少,而红色较多,说明并不可观,表示不建议使用光栅化。相反,如果在快速滚动的时候,基本都是绿色的,只有极少数偶尔出现红色,那么使用光栅化来优化是可以达到很好的效果的。

我们启动Instruments->Core Animation勾选如下选项:

下面是笔者测试的效果图:

从GIF图中可以看出来,命中率并不高,因此不适合使用光栅化来优化。

设置光栅化只需要一行代码:

1

2

3

4

 

// 光栅化

imgView.layer.shouldRasterize = YES;

 

设置上面的代码后,引起了离屏渲染:

我们要根据实际检测的结果来决定是否应该使用光栅化。

圆角引起离屏渲染

通过以下设置会引起离屏渲染:

1

2

3

4

 

imgView.layer.cornerRadius = 10;

imgView.layer.masksToBounds = YES;

 

或者这么设置:

1

2

3

4

 

//    self.headImageView.layer.cornerRadius = 30;

//    self.headImageView.clipsToBounds = YES;

 

直接设置cornerRadius属性是不会引起离屏渲染的,而且连圆角也不会有,因为只有后面的设置为YES,才会真正地渲染。

圆角引起的离屏渲染效果如下:

阴影引起离屏渲染

我们测试一下设置阴影(随意设置的):

1

2

3

4

5

 

imgView.layer.shadowColor = [UIColor redColor].CGColor;

imgView.layer.shadowOffset = CGSizeMake(10, 10);

imgView.layer.shadowOpacity = 0.8;

 

检测到离屏渲染如下图:

edge antialiasing、group opacity

笔者测试了一下,直接设置这几个,并没有检测出离屏渲染,请会的人给补上小例子。笔者的测试小例子是这么写的:

1

2

3

4

5

6

7

8

9

10

11

 

if (type == 2) {

    // 测试发现未引起离屏渲染

    imgView.layer.edgeAntialiasingMask = kCALayerTopEdge;

    imgView.layer.allowsEdgeAntialiasing = NO;

} else if (type == 3) {

    // 透明,发现未引起离屏渲染

    imgView.opaque = NO;

    imgView.layer.allowsGroupOpacity = YES;

}

 

我想肯定是笔者理解错了,不了解这几个如何去使用~后续再补上吧!

如何选择使用哪种渲染方式

摆在我们面前有三种选择:

  • 当前屏幕渲染
  • 离屏渲染
  • CPU渲染(特殊的离屏渲染)

我们应该选择使用哪种方式呢?这需要根据具体的使用场景来决定。但是,我们尽量使用当前屏幕渲染,因为离屏渲染、CPU渲染可能会带来性能问题。所以,一般情况下我们要尽量使用当前屏幕渲染。

由于GPU的浮点运算能力比CPU强,CPU渲染的效率可能不如离屏渲染;但如果仅仅是实现一个简单的效果,直接使用CPU渲染的效率又可能比离屏渲染好,因为离屏渲染要涉及到缓冲区创建和上下文切换等耗时操作。

所以,具体的选择应该要我们通过性能测试所得的结果来决定到底采用哪一种方式优化的效果会更佳。

最终优化后的效果

这里笔者去掉光栅化、去掉阴影、圆角采用生成圆角图片的方式异步加载,最终的效果如下:

已经没有黄色部分了,说明我们优化得差不多了!

源代码

本篇对应的源代码小Demo下载地址为:CoderJackyHuang:PerformaceDemo

推荐阅读

参考

时间: 2024-08-29 11:38:33

Offscreen-Rendered的相关文章

高手翻译下:True if this component has been rendered.

问题描述 高手翻译下:True if this component has been rendered. 解决方案 如果这个组件被渲染了就为true解决方案二:假如此组件已提供 则是正确的解决方案三:这个是不是extjs API里的?意思是说:"如果这个组件已经渲染,那么就为真(true)"

WWDC 2013 Session笔记 - SpriteKit快速入门和新时代iOS游戏开发指南

这是我的WWDC2013系列笔记中的一篇,完整的笔记列表请参看这篇总览.本文仅作为个人记录使用,也欢迎在许可协议范围内转载或使用,但是还烦请保留原文链接,谢谢您的理解合作.如果您觉得本站对您能有帮助,您可以使用RSS或邮件方式订阅本站,这样您将能在第一时间获取本站信息. 本文涉及到的WWDC2013 Session有 Session 502 Introduction to Sprite Kit Session 503 Designing Games with Sprite Kit SpriteK

Android动画之硬件加速

你的动画写出来卡嘛?流畅嘛 如果你想提升动画的性能,那就是用它-hardware layers. During animations your views may be redrawn each frame. If you use view layers, instead of having to redraw each frame, views render once into an off-screen buffer which can be reused. In addition, har

初次接触:DirectDraw

第六章 初次接触:DirectDraw 本章,你将初次接触DirectX中最重要的组件:DirectDraw.DirectDraw可能是DirectX中最强大的技术,因为其贯穿着2D图形绘制同时其帧缓存层也是DirectX3D的基础.当然,DirectX8.0中DirectDraw已经完全集成到了DirectX3D里面.此外,如果你对DirectDraw深有了解,那将拥有创建任何DOS16/32类型的图形化程序的能力.DirectDraw是理解众多DirectX自身概念的钥匙.所以,听仔细了.

DirectShow中写push模式的source filter流程 + 源代码(内附详细注释)

虽然网上已有很多关于DirectShow写source filter的资料,不过很多刚开始学的朋友总说讲的不是很清楚(可能其中作者省略了许多他认为简 单的过程),读者总希望看到象第一步怎么做,第二步怎么做....这样的demo.其实写你的第一个filter是有一定难度的,只要过了这关以后 就容易多了.由于最近需要自己写一个push推模式的source filter,加上刚激活了Blog,不好意思Blog上没有一篇文章,所以将写这个filter的过程写下来 ,为了照顾刚开始学的朋友,我采用第一步第

舌尖上的“谷歌”之深度评测Nexus 7平板电脑

本周谷歌在IO开发大会上发布了Nexus 7平板电脑,其中参加大会的出席者可以免费得到1台,实体机也已经在eBay开卖,而且仅售199美元.在考虑是否购买前,大家可能很想知道实际表现又如何,cnITinfo.COM就同步与其它的平板电脑作初步比较给大家参考,Nexus 7整体的表现还算不错. 不要以为价钱较为便宜,在硬件上就将货就价,性能必定有所不及.Nexus 7所采用的处理器为较低频率的1.3GHz Tegra 3 T30LSoC,四核心全负载时会是1.15GHz,比起其它采用相同SoC的平

ExtJs2.0学习系列(2)--Ext.Panel

上一篇文章ExtJs2.0学习系列(1)--Ext.MessageBox ,受到了大家的褒贬不一,还是有的朋友提出好的建议,在此表示感谢! 今天介绍extjs中的Panel组件. //html代码 <div id="container"> </div> //js代码 var p = new Ext.Panel({ title: 'My Panel',//标题 collapsible:true,//右上角上的那个收缩按钮,设为false则不显示 renderTo:

Cocoa编程之IBAction和IBOutlet含义

IBAction / IBOutlet / IBOutletCollection 时间 2014-05-05 15:00:00  NSHipster原文  http://nshipster.com/ibaction-iboutlet-iboutletcollection/ In programming, what often begins as a necessary instruction eventually becomes a vestigial cue for humans. In th

详细了解HTC中的对象

htc|对象 在微软(R)Internet Explorer 5中介绍,HTML组件(HTCs)提供一种机制来使用脚本作为动态HTML(DHTML)行为实现组件功能.以.htc扩展名保存,一份HTC是一份包含脚本和一组用于定义组件的HTC特殊元素的HTML文件.此部分包含相关元素和它们支持的成员. 对象     document                                在给定的浏览器窗口中表现HTML文档.     element