Cocos2d-x优化中纹理优化
转自 http://blog.csdn.net/tonny_guan/article/details/41016241
1.纹理像素格式
纹理优化工作的另一重要的指标是纹理像素格式,能够最大程度满足用户对保真度要求的情况下,选择合适的像素格式,可以大幅提高纹理的处理速度。而且纹理像素格式有与硬件有这密切的关系。
下面我们先了解一下纹理像素的格式,主要的格式有:
RGBA8888。32位色,它是默认的像素格式,每个通道8位(比特),每个像素4个字节。
BGRA8888。32位色,每个通道8位(比特),每个像素4个字节。
RGBA4444。16位色,每个通道4位(比特),每个像素2个字节。
RGB888。24位色,没有Alpha通道,所以没有透明度。每个通道8位(比特),每个像素3个字节。
RGB565。16位色,没有Alpha通道,所以没有透明度。R和B通道是各5位,G通道是6。
RGB5A1(或RGBA5551)。16位色,每个通道各4位,Alpha通道只用1位表示。
PVRTC4。4位PVR压缩纹理格式,PVR格式是专门为iOS设备上面的PowerVR图形芯片而设计的。它们在iOS设备上非常好用,因为可以直接加载到显卡上面,而不需要经过中间的计算转化。
PVRTC4A。具有Alpha通道的,4位PVR压缩纹理格式。
PVRTC2。2位PVR压缩纹理格式。
PVRTC2A。具有Alpha通道的,2位PVR压缩纹理格式。
此外,PVR格式在保存的时候还可以采用Gzip和zlib压缩格式进行压缩,对应的保存文件为pvr.gz和pvr.ccz。经过压缩文件会更小,加载的时候使用更少的内存!虽然是转化为纹理的时候,需要解压,但对于CPU影响很小。
2.纹理缓存异步加载
我们在启动游戏和进入场景时候,由于需要加载的资源过多就会比较“卡”,用户体验不好。我们可以采用纹理缓存(TextureCache)异步加载纹理图片,TextureCache类异步加载函数如下:
virtual void addImageAsync(const std::string & filepath,
std::function< void(Texture2D *)> callback
)
其中第一个参数文件路径,第二参数是回调函数。下面我们通过一个实例介绍一下纹理缓存异步加载使用,有200张小图片,加载到纹理缓存,加载过程会有一个进度显式在界面上,如图20-25所示。
HelloWorldScene.cpp中主要代码如下:
- bool HelloWorld::init()
- {
- if ( !Layer::init() )
- {
- return false;
- }
- Size visibleSize = Director::getInstance()->getVisibleSize();
- Vec2 origin = Director::getInstance()->getVisibleOrigin();
- auto closeItem = MenuItemImage::create(
- "CloseNormal.png",
- "CloseSelected.png",
- CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
- closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
- origin.y + closeItem->getContentSize().height/2));
- auto menu = Menu::create(closeItem, NULL);
- menu->setPosition(Vec2::ZERO);
- this->addChild(menu, 1);
- _labelLoading = Label::createWithTTF ("loading...", "fonts/Marker Felt.ttf", 35);
- _labelPercent = Label::createWithTTF ("0%%", "fonts/Marker Felt.ttf", 35);
- _labelLoading->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2 - 20));
- _labelPercent->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2 + 20));
- this->addChild(_labelLoading);
- this->addChild(_labelPercent);
- _numberOfLoadedSprites = 0;
- _imageOffset = 0;
- auto sharedFileUtils = FileUtils::getInstance();
- std::string fullPathForFilename
- = sharedFileUtils->fullPathForFilename("ImageMetaData.plist"); ①
- ValueVector vec = FileUtils::getInstance()->getValueVectorFromFile(fullPathForFilename); ②
- _numberOfSprites = vec.size(); ③
- //加载纹理
- for( auto& e : vec) ④
- {
- auto row = e.asValueMap();
- auto filename = "icons/" + row.at("filename").asString();
- Director::getInstance()->getTextureCache()->addImageAsync(filename,
- CC_CALLBACK_1(HelloWorld::loadingCallBack, this)); ⑤
- }
- return true;
- }
- void HelloWorld::loadingCallBack(Texture2D *texture) ⑥
- {
- ++_numberOfLoadedSprites;
- __String* str = __String::createWithFormat("%d%%",
- (int)(((float)_numberOfLoadedSprites / _numberOfSprites) * 100)); ⑦
- _labelPercent->setString(str->getCString()); ⑧
- Size visibleSize = Director::getInstance()->getVisibleSize();
- int i = ++_imageOffset * 60;
- auto sprite = Sprite::createWithTexture(texture); ⑨
- sprite->setAnchorPoint(Vec2(0,0));
- addChild(sprite, -1);
- sprite->setPosition(Vec2( i % (int)visibleSize.width, (i / (int)visibleSize.width) * 60));
- if (_numberOfLoadedSprites == _numberOfSprites) ⑩
- {
- _numberOfLoadedSprites = 0;
- }
- }
上述代码第①行代码是获得资源目录下ImageMetaData.plist 文件全路径,ImageMetaData.plist 文件是我们定义用来描述要加载图标文件名,文件内容如下:
- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
- "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
- <plist version="1.0">
- <array>
- <dict>
- <key>filename</key>
- <string>01-refresh.png</string>
- </dict>
- <dict>
- <key>filename</key>
- <string>02-redo.png</string>
- </dict>
- <dict>
- <key>filename</key>
- <string>03-loopback.png</string>
- </dict>
- <dict>
- <key>filename</key>
- <string>04-squiggle.png</string>
- </dict>
- … …
- </array>
- </plist>
ImageMetaData.plist 文件是属性列表文件,内部结构是数组类型,我们可以通过第②行代码FileUtils 的getValueVectorFromFile函数读入到ValueVector类型变量vec中。第③行代码_numberOfSprites = vec.size()是获得数组的长度,然后赋值给成员变量_numberOfSprites为了能够计算加载进度。
第④行代码是循环遍历数组,数组结构中的每一个元素是键值对结构,取的键值对结构语句是auto row = e.asValueMap()。然后通过语句row.at("filename").asString()从键值对对象row中取出键为filename对应的值。
第⑤行代码是调用TextureCache的addImageAsync函数实现异步加载图片缓存,HelloWorld::loadingCallBack是回调函数,this参数表示回调函数的目标对象。
第⑥行是我们定义的回调函数实现。第⑦行代码在的表达式(int)(((float)_numberOfLoadedSprites / _numberOfSprites) * 100)可以计数出加装进度,"%d%%"可以显示百分号,其中的%d是格式化输出数字。%%是输出%,前面%起到转义作用。第⑧行代码_labelPercent->setString(str->getCString())是设置进度标签_labelPercent的内容。
第⑨行代码auto sprite = Sprite::createWithTexture(texture)是通过纹理对象texture创建精灵对象。第⑩行代码if (_numberOfLoadedSprites == _numberOfSprites)是判断是否完成任务,_numberOfLoadedSprites是已经加装的图片数,_numberOfSprites是要加装的全部图片数。
Cocos2d-x优化中纹理优化的更多相关文章
- Cocos2d-x优化中图片优化
在2D游戏中图片无疑是最为重要的资源文件,它会被加载到内存中转换为纹理,由GPU贴在精灵之上渲染出来.它能够优化的方面很多,包括:图片格式.拼图和纹理格式等,下面我们从这几个方面介绍一下图片和纹理的优 ...
- 转 iOS和android游戏纹理优化和内存优化(cocos2d-x)
iOS和android游戏纹理优化和内存优化(cocos2d-x) (未完成) 1.2d游戏最占内存的无疑是图片资源. 2.cocos2d-x不同平台读取纹理的机制不同.ios下面使用CGImage, ...
- cocos2d-x3.2中怎样优化Cocos2d-X游戏的内存
在游戏项目优化中都会碰到一个问题,怎样既能降低内存又能尽量降低包的大小?在实际项目中有些经验分享一下,其实2D游戏中最占内存的就是图片资源,一张图片使用不同的纹理格式带来的性能差异巨大.下表是我在IO ...
- Unity教程之再谈Unity中的优化技术
这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的”顶点 ...
- 【Unity技巧】Unity中的优化技术
http://blog.csdn.net/candycat1992/article/details/42127811 写在前面 这一篇是在Digital Tutors的一个系列教程的基础上总结扩展而得 ...
- 【转】Cocos2d-x纹理优化的一些方案——2013-08-26 22
http://wap.oschina.net/question/565065_79814 在目前的移动平台游戏开发过程中,很多朋友会遇到开发出来的DEMO占用内存过大,导致渲染效率低下的问题.究其原因 ...
- Unity中的优化技术
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/candycat1992/article/ ...
- django缓存优化中caches参数如何配置?
在python开发中,如果运营django进行编写,为了提升效率,常常需要优化缓存,缓存优化中必须掌握的caches参数相关知识: CACHES 配置参数概述 - 格式 CACHES 字典配置格式如下 ...
- mysql中的优化, 简单的说了一下垂直分表, 水平分表(有几种模运算),读写分离.
一.mysql中的优化 where语句的优化 1.尽量避免在 where 子句中对字段进行表达式操作select id from uinfo_jifen where jifen/60 > 100 ...
随机推荐
- Positional parameter are considered deprecated; use named parameters or JPA-style positional parameters instead.
这行代码: List<Cat> catList =session.createQuery("from Cat p where p.name.first_name=?") ...
- Shell之while循环
While循环的格式: while expression do command command ... done 1.计数器控制的while循环:主要用于已经准确知道要输入的数据和字符串的数目. 例子 ...
- Oracle将表keep到内存
一.引言: 有时候一些基础表需要非常的频繁访问,尤其是在一些循环中,对该表中的访问速度将变的非常重要.为了提高系统的处理性能,可以考虑将一些表及索引读取并保存到内存中. 二.关于keep内存的几个参数 ...
- php如何支持实现多线程并发
<?php if(function_exists('date_default_timezone_set')) { date_default_timezone_set('PRC'); } func ...
- IOS5基础教程之一-----如何创建XCode项目
一.IOS的基础知识 1.只有一个应用程序正在运行.在IOS上,每一段时间内只能激活一个应用程序并在屏幕上显示. 2.只有一个窗口.只允许应用程序操作的一个窗口. 3.访问受限.只能在IOS为应用程序 ...
- DOM元素尺寸和位置
一.获取元素 CSS大小 1.通过style 内联获取元素的大小 var box = document.getElementById('box'); //获取元素 box.style.width; / ...
- pg_dump 备份与恢复的简单操作
pg_dump 是一个用于备份PostgreSQL数据库的工具. 该工具生成的转储格式可以分为两种, 脚本 : 其中脚本格式是包含许多SQL命令的纯文本格式 (常用) 归 ...
- ACM题目————The partial sum problem
描述 One day,Tom’s girlfriend give him an array A which contains N integers and asked him:Can you choo ...
- oracle闪回查询
一.引言 程序中用到需要同步oracle更新和删除数据,于是考虑利用oracle的闪回查询机制来实现. 利用该机制首先需要oracle启用撤销表空间自动管理回滚信息,并根据实际情况设置对数据保存的有效 ...
- ubuntu安装和查看已安装
说明:由于图形化界面方法(如Add/Remove... 和Synaptic Package Manageer)比较简单,所以这里主要总结在终端通过命令行方式进行的软件包安装.卸载和删除的方法. 一.U ...