纹理优化工作的另一重要的指标是纹理像素格式,能够最大程度满足用户对保真度要求的情况下,选择合适的像素格式,可以大幅提高纹理的处理速度。而且纹理像素格式有与硬件有这密切的关系。
下面我们先了解一下纹理像素的格式,主要的格式有:
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中主要代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@H_502_114@
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
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"
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/
2
301@
auto menu = Menu::create(closeItem,NULL);
menu->setPosition(Vec2::ZERO);
->addChild(menu,
1
);
_labelLoading = Label::createWithTTF (
"loading..."
"fonts/Marker Felt.ttf"
35
);
_labelPercent = Label::createWithTTF (
"0%%"
);
_labelLoading->setPosition(Vec2(visibleSize.width /
-
20
));
_labelPercent->setPosition(Vec2(visibleSize.width /
+
));
->addChild(_labelLoading);
->addChild(_labelPercent);
_numberOfLoadedSprites =
0
;
_imageOffset =
;
auto sharedFileUtils = FileUtils::getInstance();
std::string fullPathForFilename
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,monospace!important; font-size:1em!important; min-height:inherit!important; background:none!important">)); ⑤
}
true
;
}
void
HelloWorld::loadingCallBack(Texture2D *texture) ⑥
{
++_numberOfLoadedSprites;
__String* str = __String::createWithFormat(
"%d%%"
_labelPercent->setString(str->getCString()); ⑧
Size visibleSize = Director::getInstance()->getVisibleSize();
i = ++_imageOffset *
60
;
auto sprite = Sprite::createWithTexture(texture); ⑨
sprite->setAnchorPoint(Vec2(
));
addChild(sprite,-
);
sprite->setPosition(Vec2( i % (
)visibleSize.width,(i / (
)visibleSize.width) *
));
(_numberOfLoadedSprites == _numberOfSprites) ⑩
{
;
}
}
|
上述代码第①行代码是获得资源目录下ImageMetaData.plist 文件全路径,ImageMetaData.plist 文件是我们定义用来描述要加载图标文件名,文件内容如下:
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<plist version=
>
<dict>
<key>filename</key>
<string>
01
-refresh.png</string>
</dict>
<dict>
<key>filename</key>
02
-redo.png</string>
</dict>
<dict>
<key>filename</key>
03
-loopback.png</string>
</dict>
<dict>
<key>filename</key>
04
-squiggle.png</string>
</dict>
… …
</array>
</plist>
|