Cocos2d-x C++ Sprite、Texture2D、TextureCache、SpriteBatchNode、SpriteFrame、SpriteFrameCache及相關類 源碼簡析

文章目錄

Sprite

簡介

Sprite是一個顯示2D圖像的節點,可以根據圖片、紋理、精靈幀(或其一部分矩形區域)創建。使用圖片創建時,會先根據文件名從TextureCache中查找紋理緩存,詳情參見TextureCache。

渲染模式

QUAD(默認模式)

渲染一個矩形區域(由兩個三角形構成),內存佔用較小,但在圖片未填滿矩形區域的情況下會渲染空像素(較慢)。

POLYGON

使用大量三角形區域(數量由設置決定)進行渲染,佔用內存較多,但可以避免渲染大量的空像素(較快)。可以調用setPolygonInfo()更換到此模式。

SLICE9

將圖片分爲3*3的區域,渲染9個矩形區域(由18個三角形區域構成),中間的矩形區域可以進行拉伸,而其他8個區域保持不變,一般用於不定長圖形等。可以調用setCenterRect()或serCenterRectNormalized()更換到此模式。

QUAD_BATCHNODE

多個節點在一個批次中渲染的模式,但有許多限制,詳情參見SpriteBatchNode。將節點添加至SpriteBatchNode的子節點中即更換到此模式。

SLICE9渲染模式的應用

優化渲染

  1. 使用SpriteFrameCache中的圖集創建Sprite,詳情參見SpriteFrameCache。
  2. 多個Sprite儘量使用同一種渲染模式。

屬性介紹

當節點由圖集渲染時使用以下屬性

_textureAtlas、_atlasIndex

SpriteBatchNode所用的圖集及所用圖片的實際下標(弱引用,不增加引用計數),詳情參見TextureAtlas。

_batchNode

此節點所屬的SpriteBatchNode節點(弱引用,不增加引用計數),詳情參見SpriteBatchNode。

當節點由自身渲染時使用以下屬性

_blendFunc

顏色混合方式,詳情參見TextureProtocol。

_texture、_rect、_rectRotated

節點使用的材質、所用的矩形範圍(默認爲材質大小)以及矩形是否經過旋轉,詳情參見Texture2D。

當節點渲染模式爲slice 9使用以下屬性

_centerRectNormalized

指定slice 9的中心區域的矩形。

以下爲通用屬性

_renderMode

節點的渲染模式。

_stretchFactor、_stretchEnabled

節點的拉伸比例以及是否開啓拉伸(翻轉X/Y軸,設置大小等視爲進行拉伸,Scale不視爲拉伸)。QUAD模式需要通過此值計算偏移量,slice 9模式需要通過此值計算不同區域的矩形拉伸,Polygon和QUAD_BATCHNODE模式不使用此值。

_opacityModifyRGB

修改透明度是否會同步修改RGB數值。

_flippedX、_flippedY

是否沿X/Y軸翻轉。

_insideBounds

Sprite上一幀時是否在可視邊界內。

_fileName、_fileType

Sprite使用的紋理對應的圖片名和類型。

_spriteFrame

Sprite使用的精靈幀。如果該Sprite不是由圖集創建的,則此值爲nullptr,在調用getter時纔會動態的根據Texture創建SpriteFrame並返回(此節點不保持這個SpriteFrame的引用,如果值爲nullptr每次調用getter都會返回新的SpriteFrame),詳情參見SpriteFrame。

爲什麼修改了SpriteFrame卻沒有效果?

_trianglesCommand

存儲這個節點的渲染指令。

函數介紹

void setTexture(Texture2D *texture)

設置新紋理,同時會重置紋理區域到紋理的大小。如果將紋理置nullptr,不會使_texture變量變爲nullptr而會使用一個2*2的白色默認圖片取代。

void setSpriteFrame(SpriteFrame *spriteFrame)

設置新的精靈幀,如果紋理不同會同時更新紋理。

void setDisplayFrameWithAnimationName(const string& animationName, ssize_t frameIndex)

設置Sprite的SpriteFrame爲從動畫幀中某一時刻的SpriteFrame。

TextureProtocol

BlendProtocol的子類,在定義了顏色混合方式的基礎上增加了對Texture的getter/setter。

BlendProtocol

簡介

OpenGL的顏色混合協議,存儲決定使用哪種顏色混合方式的變量。

BlendFunc

用來代表某種顏色混合方式的結構體,決定當節點渲染時對每個像素點如何進行顏色混合。src屬性代表源節點使用的混合方式,dst代表目標節點使用的混合方式,引擎給出了幾種常用的混合方式。詳情參見此處

DISABLE

忽略目標點的RGBA,使用源點RGBA完全覆蓋。

ALPHA_PREMULTIPLIED

目標點RGBA根據源點透明度進行修正,源點RGBA不變後進行疊加。

ALPHA_NON_PREMULTIPLIED

目標點RGBA根據源點透明度進行修正,源點RGBA同樣根據透明度修正後疊加。

ADDITIVE

目標點RGBA不變,源點RGBA根據自身透明度修正後疊加。

Texture2D

簡介

處理OpenGL中2D紋理的類,可以通過圖片、文本、源數據快速創建紋理。紋理中的實際圖片大小可能會小於紋理大小。

注意:生成的紋理數據是倒置的。

Texture2D不會被自動釋放(除了異步加載時),當不使用時需要手動調用release函數或使用TextureCache進行釋放。

Texture2D的內存管理和其他類的區別

函數介紹

static void setDefaultAlphaPixelFormat(PixelFormat format)

設置新創建紋理的默認像素格式。擁有透明度的圖片將使用默認的像素格式,而不含透明度的圖片在默認格式是RGBA8888的的情況下使用RGBA8888,其他默認格式則使用RGB565(因此圖片應使用含透明度的格式,以確保在程序中的像素格式可以自己控制)。

這個函數不影響pvr/pvr.ccz格式的圖片。

爲什麼調用此函數沒有改變像素格式?

void releaseGLTexture()

僅釋放OpenGL中當前對應的紋理(不釋放當前對象)。

void setAliasTexParameters()

給紋理添加抗鋸齒。

void setAntiAliasTexParameters()

給紋理添加平滑過渡。

PixelFormat

簡介

Texture2D的像素格式枚舉。其中R代表紅色通道數值,G代表綠色通道數值,B代表藍色通道數值,A代表透明度通道數值。

BGRA8888、RGBA8888

RGBA通道數值各佔8位,一個像素佔4字節,標準像素格式。

RGB888

去除了透明度通道的格式,一個像素佔3字節,對於不透明圖片可以在保持畫質的情況下節省空間。去除了透明度通道僅代表圖片沒有透明像素,而在引擎中仍然可以對其更改透明度(節點的透明度與紋理中像素的透明度無關)。

RGB565

R、B通道佔5位,G通道佔6位,一個像素佔2字節,以畫質爲代價進一步節省了空間。

A8

顏色只有黑色(無視圖像原本的顏色),只有8位透明度通道的格式,一個像素佔1字節,通常用於蒙版遮罩。

I8

只有亮度(黑白度)的格式,圖像爲黑白色且沒用透明度通道,一個像素佔1字節。

AI88

亮度和透明度通道各佔8位的格式,一個像素佔2字節,通常用於蒙版遮罩。

RGBA4444

RGBA通道數值各佔4位,一個像素佔2字節,畫質損失最嚴重的格式。

RGB5A1

RGB通道數值各佔5位,A通道佔1位,一個像素佔2字節,適用於只有全透明像素和非透明像素的圖片。

PVRTC、ETC、ATITC

分別代表3種壓縮格式,其中pvrtc只能用於ios,安卓官方規定格式是etc,attic是高通adreno系列GPU支持的格式。

PixelFormatInfo

與PixelFormat相對應的各像素格式的具體信息。

FontDefinition

文字作爲圖片顯示時的一些參數定義。

TextureCache

簡介

TextureCache可以緩存加載過的紋理,節省加載重複紋理時的時間。但如果有不需要的紋理需要手動調用removeTexture函數進行釋放,否則會持續佔用內存。

屬性介紹

_loadingThread

用於紋理異步加載的線程的引用。

_asyncStructQueue、_requestQueue、_responseQueue

用於異步加載紋理時存儲需要加載的信息和結果的隊列。

_requestMutex、_responseMutex

用於異步加載紋理的線程鎖。

_sleepCondition

用於在需要異步加載紋理時喚醒加載線程。

_needQuit

是否正在等待結束遊戲。

_asyncRefCount

異步加載的紋理個數。

_textures

緩存的紋理,使用unordered_map存儲。

s_etc1AlphaFileSuffix

圖片使用etc1壓縮時,透明度通道存儲的文件的後綴。

函數介紹

void addImageAsync(const string &path, const function<void(Texture2D*)>& callback, const string& callbackKey)

異步加載紋理,加載完成後調用回調函數,callbackKey用於取消特定的異步加載回調。如果紋理已經加載將立刻調用回調函數。

加載步驟:

  1. 根據需要加載的信息構造AsyncStruct結構體,加線程鎖後放入_requestQueue中,同時喚醒加載線程,爲主線程添加定時器。
  2. 線程從_requestQueue中取出結構體,進行加載。
  3. 加載完成後加載線程加線程鎖後把紋理指針放入_responseQueue中,然後線程等待。
  4. 主線程中定時器每幀調用,判斷_responseQueue中是否有數據,如果有則進行處理並調用異步加載回調。
  5. 若異步加載隊列數量爲0,則定時器會銷燬自身。

異步加載的Texture會被自動釋放。

void unbindImageAsync(const string& callbackKey)

取消執行指定異步加載的回調函數(指定的紋理仍會被加載,然後在加載的那幀結束時被自動釋放)。

void loadImage()

加載線程執行的函數。

void addImageAsyncCallBack(float dt)

主線程中定時執行用於檢測異步加載是否完成的函數。

Texture2D* addImage(const string &path)

在主線程中加載紋理,如果已在緩存中存在則直接返回。

void parseNinePatchImage(Image *image, Texture2D *texture, const string& path)

判斷圖片是否爲9Patch圖片,如果是則將紋理轉換爲9Patch類型。

bool reloadTexture(const string& fileName)

從紋理中重新加載紋理,如果未加載過也會進行加載。

void removeAllTextures()

移除對所有紋理的引用(除非紋理只有這一個引用,否則不會被釋放)。

void reloadAllTextures()

此函數內容爲空,如果想重新加載所有紋理請手動遍歷調用reloadTexture函數。

void waitForQuit()

在遊戲退出時被Director調用,用於等待加載線程結束。

string getCachedTextureInfo() const

返回所有緩存的Texture的詳細信息,一般用於調試時查看內存佔用。

AsyncStruct

記錄圖片異步加載信息的結構體,包括了返回狀態、加載文件名、加載回調函數等信息。

TextureAtlas

TextureAtlas(紋理圖集)可以在運行時手動更新QUAD(每個Sprite後代對應一個QUAD),並使用VBO進行渲染,效率更高,詳情參見此處

SpriteBatchNode

簡介

SpriteBatchNode用於批量繪製同一個紋理(即同一張Image、同一個TextureAtlas)的Sprite。次節點的所有後代的渲染模式爲QUAD_BATCHNODE,會在一次OpenGL調用時全部繪製,消耗更少的性能。通常此節點與存儲在SpriteFrameCache中的圖集配合使用。此節點的Texture存儲在TextureAtlas中,渲染時只使用SpriteBatchNode的TextureAtlas進行渲染以提升性能。

注意:此節點的所有後代都必須是Sprite且使用相同紋理,且所有節點共享抗鋸齒(Aliased)和平滑過渡(Antialiased)屬性,因爲這些是屬於紋理的。

只有添加了QUAD到TextureAtlas中的節點纔會被繪製,添加節點而不添加QUAD、移除QUAD而不移除節點的節點都不會被繪製。

屬性介紹

DEFAULT_CAPACITY

TextureAtlas中QUAD、子節點和後代節點數組的默認大小,如果TextureAtlas中的QUAD數組容量不夠每次擴容1/3。

_descendants

該SpriteBatchNode的所有後代節點。

函數介紹

static SpriteBatchNode* create(const string& fileImage, ssize_t capacity = DEFAULT_CAPACITY)

根據圖片名創建SpriteBatchNode,圖片名爲該節點樹下的節點必須所屬的圖片名。

注意:如果使用圖集,則應傳入圖片名而非plist後綴的名字,或者使用createWithTexture函數更方便。

SpriteFrame

記錄Sprite所使用的Texture、使用的區域、大小、錨點等,對於圖集來說非常重要(圖集中不同的區域代表了不同的圖片)。當需要修改某個Sprite的圖片時,應修改SpriteFrame而不是修改Texture。修改Texture會修改所有使用此紋理的Sprite(如果是圖集的話會修改所有使用此圖集的Sprite),而修改SpriteFrame只會修改單個Sprite(除非你將這個Sprite作用於了多了Sprite)。

如果需要將圖片修改成同一圖集中的其他圖片,只需要改變SpriteFrame所在Texture的區域即可。

SpriteFrameCache

簡介

存儲由圖集創建的精靈幀的緩存(自己創建的與直接用圖片/材質創建的精靈幀不會緩存)。緩存具體由PlistFramesCache管理。由圖集創建的SpriteFrame應在不用時手動進行remove防止持續佔用內存。

PlistFramesCache

簡介

通過Plist加載的SpriteFrame的緩存。

屬性介紹

_spriteFrames

緩存中所有SpriteFrame名與引用的映射。

_indexPlist2Frames

緩存中plist名與對應的SpriteFrame名的集合的映射。

_indexFrame2plist

SpriteFrame名與對應的plist名的映射。

_isPlistFull

存儲對應的plist名是否加載。

使用圖集可以減少哪些方面的性能損耗?

相關OpenGL函數

glPixelStorei

設置OpenGL每次讀取的字節數,如果設置不當導致會導致越界讀取進而導致圖像錯誤、程序崩潰等。

glDeleteTextures

根據id刪除OpenGL中對應的紋理。

glGenTextures

在OpenGL中生成紋理,並返回紋理對應的id。

glTexParameteri

圖象從紋理映射到顯存時,需要使用這個函數來確定映射的方式。

glCompressedTexImage2D/glTexImage2D

將壓縮/未壓縮的紋理映射至緩存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章