紋理優化工作的另一重要的指標是紋理像素格式,能夠最大程度滿足用戶對保真度要求的情況下,選擇合適的像素格式,可以大幅提高紋理的處理速度。而且紋理像素格式有與硬件有這密切的關係。
下面我們先了解一下紋理像素的格式,主要的格式有:
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
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" , 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 文件是我們定義用來描述要加載圖標文件名,文件內容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<!--?xml
version= "1.0"
encoding= "utf-8" ?--> <plist
version= "1.0" > <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是要加裝的全部圖片數
http://www.2cto.com/kf/201411/351657.html