• Cocos2d-x优化中纹理优化


    转自 http://blog.csdn.net/tonny_guan/article/details/41016241

    Cocos2d-x优化中纹理优化

    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中主要代码如下:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. bool HelloWorld::init()  
    2. {  
    3.     if ( !Layer::init() )  
    4.     {  
    5.         return false;  
    6.     }  
    7.   
    8.   
    9.     Size visibleSize = Director::getInstance()->getVisibleSize();  
    10.     Vec2 origin = Director::getInstance()->getVisibleOrigin();  
    11.     auto closeItem = MenuItemImage::create(  
    12.         "CloseNormal.png",  
    13.         "CloseSelected.png",  
    14.         CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));  
    15.   
    16.   
    17.     closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,  
    18.         origin.y + closeItem->getContentSize().height/2));  
    19.     auto menu = Menu::create(closeItem, NULL);  
    20.     menu->setPosition(Vec2::ZERO);  
    21.     this->addChild(menu, 1);  
    22.   
    23.   
    24.     _labelLoading = Label::createWithTTF ("loading...", "fonts/Marker Felt.ttf", 35);  
    25.     _labelPercent = Label::createWithTTF ("0%%", "fonts/Marker Felt.ttf", 35);  
    26.   
    27.   
    28.     _labelLoading->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2 - 20));  
    29.     _labelPercent->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2 + 20));  
    30.   
    31.   
    32.     this->addChild(_labelLoading);  
    33.     this->addChild(_labelPercent);  
    34.   
    35.   
    36.     _numberOfLoadedSprites = 0;  
    37.     _imageOffset = 0;  
    38.   
    39.   
    40.     auto sharedFileUtils = FileUtils::getInstance();  
    41.     std::string fullPathForFilename   
    42.                 = sharedFileUtils->fullPathForFilename("ImageMetaData.plist");               ①  
    43.   
    44.   
    45.     ValueVector vec = FileUtils::getInstance()->getValueVectorFromFile(fullPathForFilename);     ②  
    46.     _numberOfSprites = vec.size();                                          ③  
    47.     //加载纹理  
    48.     for( auto& e : vec)                                                     ④  
    49.     {   
    50.         auto row = e.asValueMap();  
    51.         auto filename = "icons/" + row.at("filename").asString();         
    52.         Director::getInstance()->getTextureCache()->addImageAsync(filename,  
    53.                 CC_CALLBACK_1(HelloWorld::loadingCallBack, this));                  ⑤  
    54.     }  
    55.     return true;  
    56. }  
    57.   
    58.   
    59. void HelloWorld::loadingCallBack(Texture2D *texture)                                ⑥  
    60. {  
    61.     ++_numberOfLoadedSprites;  
    62.     __String* str = __String::createWithFormat("%d%%",   
    63.                         (int)(((float)_numberOfLoadedSprites / _numberOfSprites) * 100));       ⑦  
    64.     _labelPercent->setString(str->getCString());                                  ⑧  
    65.   
    66.   
    67.     Size visibleSize = Director::getInstance()->getVisibleSize();  
    68.     int i = ++_imageOffset * 60;  
    69.   
    70.   
    71.     auto sprite = Sprite::createWithTexture(texture);                               ⑨  
    72.     sprite->setAnchorPoint(Vec2(0,0));  
    73.     addChild(sprite, -1);  
    74.     sprite->setPosition(Vec2( i % (int)visibleSize.width, (i / (int)visibleSize.width) * 60));  
    75.   
    76.   
    77.     if (_numberOfLoadedSprites == _numberOfSprites)                             ⑩  
    78.     {  
    79.         _numberOfLoadedSprites = 0;  
    80.     }  
    81. }  



    上述代码第①行代码是获得资源目录下ImageMetaData.plist 文件全路径,ImageMetaData.plist 文件是我们定义用来描述要加载图标文件名,文件内容如下:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"   
    3.                 "http://www.apple.com/DTDs/PropertyList-1.0.dtd">  
    4. <plist version="1.0">  
    5.   <array>  
    6.     <dict>  
    7.       <key>filename</key>  
    8.       <string>01-refresh.png</string>  
    9.     </dict>  
    10.     <dict>  
    11.       <key>filename</key>  
    12.       <string>02-redo.png</string>  
    13.     </dict>  
    14.     <dict>  
    15.       <key>filename</key>  
    16.       <string>03-loopback.png</string>  
    17.     </dict>  
    18.     <dict>  
    19.       <key>filename</key>  
    20.       <string>04-squiggle.png</string>  
    21.     </dict>  
    22.    … …    
    23.   </array>  
    24. </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是要加装的全部图片数。

  • 相关阅读:
    可惜老板不看程序员写的书
    《让僵冷的翅膀飞起来》系列之四——Visitor模式之可行与不可爱
    《让僵冷的翅膀飞起来》系列之二——从实例谈Adapter模式
    策略模式的应用实践
    《让僵冷的翅膀飞起来》系列之三——从Adapter模式到Decorator模式
    用Design+Blend轻松制作环形文字
    silverlight3的"伪"3D续图片横向轮换
    silverlight.net官方网站图片切换源码
    css2.1中的属性选择器(css高手请绕道)
    多线程中的ManualResetEvent
  • 原文地址:https://www.cnblogs.com/rexzhao/p/4233645.html
Copyright © 2020-2023  润新知