cocos2d-x渲染架構

        3.0之前是visit後就draw,而draw是真正的OpenGL操作。也就是說,每訪問一個對象,先計算節點的渲染數據,然後馬上渲染。因爲節點是按樹形結構組織的,如果兩個父節點p1和p2的深度分別是10和20,c1是p1的子節點,其深度是30,c2是p2的子節點,其深度是5。則渲染順序是p1、c1、c2、p2。

        3.0也是在visit後就draw,但是draw並不進行OpenGL操作。3.0抽象了一個RenderCommand,在draw的時候其實是生成一個渲染命令,渲染命令其實就是對渲染所需要的數據的封裝。RenderCommand作爲基類,只包含了兩個成員,一個是命令類型_type,這個很必要,正是靠這個來獲取子類對象的具體類型的,這裏沒有用運行時類型,應該是考慮到效率;另一個是z深度_globalOrder,這個也很必要,渲染的時候必然要對節點排序,而z序是唯一的依據。

        3.0包含了以下幾個RenderCommand的子類:

        1,CustomCommand:

        顧名思義,是客戶自定義的。它沒有過多的數據,只有一個std::function<>類型成員func,這個是在節點draw創建CustomCommand的時候傳入的參數,而在真正渲染的時候調用的正是這個函數。比如Label,它的draw函數體爲:

void Label::draw()

{

    _customCommand.init(_globalOrder);

   _customCommand.func=CC_CALLBACK_0(Label::onDraw, this,transform,transformUpdated);

   render->addCommand(&_customCommand);

}

        可見,真正的渲染是在onDraw回調函數中。onDraw的操作和此前版本的draw函數相差不大,都是設置混合方式,使用GLProgram,更新shader的變換矩陣等shader所用到的uniform變量,更新子節點位置(注:因爲是批量渲染,這個和此前的CCSpriteBatchNode很相近),調用TextureAtlas::drawQuads();

使用CustomCommand還有Layer,LableAtlas,LabelBMFont,此外還有RenderTexture,這個比較特殊,下面會說。

        注:估計作者是對所有不太好抽象的渲染節點,就乾脆做了一個CustomCommand。

        2,QuadCommand:

        和CustomCommand不同,這個類包含了很多屬性:紋理_textureID,Program _shader,混合函數_blendType,定點數據_quad,模型視圖矩陣_mv,還有一個材質屬性_materialID。材質是一種抽象,當且僅當紋理、shader、混合函數都相等的時候,材質才相等。抽象材質的好處是,如果兩個對象渲染順序相鄰,且材質相同,就可以使用批量渲染。當然,兩個對象必須都使用QuadCommand,因爲只有QuadCommand纔有材質屬性。

        QuadCommand的最終渲染操作放在了Render::drawBatchQuads中,其輸入是一個所有QuadCommand的頂點排序後組裝成的VBO,一個是這些定點對應的QuadCommand命令數組。查看這個函數也的確是當材質發生變化的時候才進行一次渲染,可見它是把相同材質的放到了一起批量渲染。

        值得一提的是3.0主要是對QuadCommand進行了優化,實際上游戲中也大多數是這種情況。在Render::render()函數中,如果當前是QuadCommand,則頂點和Command放入數組,如果是其它,則先渲染此前的QuadCommand數組,然後再渲染當前命令。

        使用QuadCommand命令的類有Sprite,ParticleSystemQuad,而Sprite應該是遊戲中最常用的類,所以3.0的優化還是很有意義的。

        3,BatchCommand:

看名字就知道,BatchCommand是CCSpriteBatchNode的改進,而事實上,也的確是CCSpriteBatchNode和CCPaticleBatchNode使用了BatchCommand。BatchCommand的屬性和QuadCommand很相似,不過沒有了頂點數據_quad,變成了_textureAtlas,其渲染函數也和此前的差別不大,都是材質三劍客(shader, texutre, blend),然後是更新shader的uniform變量,最後調用_textureAtlas->drawQuads(),和Label的渲染很相似,只不過Label的更新子節點的頂點放在了渲染函數中,而BatchCommdand放在了節點的visit中,具體可參加源代碼。

        4,GroupCommand:

        這是一個Command組合,但是GroupCommand只有一個屬性_renderQueueID,而GroupCommand的所有子Command其實存放在Render中。GroupCommand像其它Command一樣,存放在同一個隊列中,遍歷的時候,如果是GroupCommand,則獲取其_renderQueueID,然後根據_renderQueueID找到指定的RenderCommand隊列,進而渲染這個隊列。可見,在Render中,可以包含多個Command隊列,一些是根節點隊列(沒有父Command),其它的是指定ID的GroupCommand的子命令隊列。

        使用GroupCommand的主要有RenderTexture,因爲RenderTexture包含了兩次分隔的渲染操作,一次是begin(),一次是end()。

        引擎只提供了四種RenderCommand,用的最廣泛的是QuadCommand。這些遠遠不夠,比如沒有支持多重紋理。

        如果我想在Sprite上加入一個多重紋理的功能,應該怎麼辦?是擴展QuadCommand還重新創建一個新的RenderCommand?

 

轉載出處:http://blog.csdn.net/zhangshuliai/article/details/25740343

參考:http://blog.csdn.net/bill_man/article/category/1060940

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