Cocos2d x 3 0 新的點染架構

2021-06-20 04:43:18 字數 2728 閱讀 8158

cocos2d-x 3.0 新的渲染架構

8月1號這一天,cocos2d-x 官方微博上說 x 團隊正在糾結是否用智慧型指標替換現有的引用計數記憶體管理機制,結果引發大家的爭論。

在我看來,引發這個爭論的原因是 cocos2d-x 打算實現多執行緒化,從而充分利用現代智慧型手機的多核處理器資源。而多執行緒化的乙個最重大需求,應該就是 cocos2d-x 3.0 新的渲染架構了。

cocos2d-x 3.0 的渲染架構設計來自 zynga(原始設計文件)。在這個架構設計中,遊戲將分為兩個主要的執行緒:main thread 和 draw thread。

main thread 執行遊戲的邏輯**,例如在場景的 update() 函式中改變角色位置、在 schedule selector 函式中建立新敵人等等。

main thread 中的**會改變 scene 中的 node tree,但並不實際執行 opengl 渲染操作。作為替代,main thread 將繪圖操作轉換為一系列的 draw command,傳送到乙個 queue 中。

draw thread 則在每一幀繪製前,從 queue 裡提取 draw command,然後進行優化,再轉換為實際的 opengl 渲染操作。

在單執行緒架構中,遊戲邏輯和渲染操作是順序執行的。兩者消耗的時間加起來如果超過 1/60 秒,就會導致遊戲出現卡頓現象。

分成多執行緒後,main thread 有更多的時間來執行遊戲邏輯。而 draw thread 也有更多的時間做優化和渲染操作,例如實現 automatic batching。

新渲染架構可能的實現方案

zynga 的設計文件並沒有給出細節實現原理,我就以大家討論的內容整理了乙個可能的方案。

main thread 會每 1/60 秒的頻率呼叫 scene::drawscene() 方法。這個方法有如下步驟:

傳送乙個 begin command 到乙個 command queue

update() 執行所有的 schedule selector 和 event listener,遊戲邏輯大部分就在其中。

掃瞄整個 node tree,構造一系列 draw command,併發送到 queue

傳送乙個 end command 到 queue,形成乙個完整的 commands list

如果某次 drawscene() 消耗的時間超過 1/60 秒,則無需等待,立即開始下一次 drawscene() 呼叫。這樣確保遊戲的邏輯能夠以最高 60fps 執行,但又不會超過 60fps。

draw thread 按照如下步驟以最快 1/60 秒的頻率執行:

從 queue 中找出最後一組 list(如果 draw thread 每次繪圖消耗時間超過 1/60 秒,queue 中就可能包含多組 list,放棄之前的 list 可以確保畫面符合最近的遊戲狀態)。

對 list 進行處理,執行畫面渲染。

更新 queue,刪除已繪製的 list 及其之前的所有 list。

texture 物件不再儲存材質的實際資料,改為儲存乙個 texture id。材質的實際資料由 draw thread 進行管理。

當載入乙個材質檔案時,main thread 中構造乙個新的 texture 物件,並獲得乙個新的 texture id。然後傳送 load texture command,並將材質檔名和 texture id 作為 command 的引數傳遞給 draw thread。draw thread 可以在自己執行緒裡載入材質資料,或新開執行緒載入資料。

當乙個 texture 被 sprite 使用時,增加 texture 物件的引用計數。而使用該 texture 的 sprite 刪除時,則減小引用計數。如果 texturecache 需要釋放不再引用計數為 0 的 texture 物件,就傳送 release texture command。

在 cocos2d-x 2.x 版中,ccnode 包含了位置、大小、縮放、旋轉等資訊,以及 opengl 繪圖需要的資料。

在新架構裡,main thread 維護的 node tree 中,node 不再包含 opengl 繪圖需要的資料。而是在構造 node、改變 node 狀態時,才將 node 的狀態資料傳送給 draw thread。

draw thread 根據 node id 維護 node 的繪圖資料。

如果 main thread 執行後,node 的狀態沒有發生改變,就無需傳送該 node 的 draw command,也就避免了 draw thread 對沒有發生變化的 node 重新計算繪圖資料。

cocos2d-x 3.0 必須要實現執行緒安全?

在整個設計裡,main thread 不停的往 command queue 追加資料,而 draw thread 每完成一次畫面渲染就清理一次 command queue。因此 queue 的實現必須是執行緒安全的,主要的操作都應該滿足原子性要求。

但從這個設計看,只要保證兩點,那麼 main thread 裡的物件是不是執行緒安全根本無所謂:

queue 是執行緒安全的

draw thread 不使用自動釋放的引用計數物件

所以這樣一番分析後,感覺 cocos2d-x 3.0 要多執行緒化,就不一定要做大改動。

但實際上 cocos2d-x 3.0 裡還需要多執行緒完成非同步 io(例如網路)、非同步計算等等。而且提供乙個可靠的執行緒安全架構,也方便開發者建立執行緒來優化遊戲體驗(比如把 ai 演算法放入單獨的執行緒)。

所以從整體架構上看,cocos2d-x 3.0 實現執行緒安全還是很有必要的。但實現執行緒安全是否就一定要用智慧型指標嗎?這個我會另外寫一篇文章來**此問題。

- end - -

cocos2d x 3 0 編譯問題

3.0最主要的問題是它引進了c 11 所有ndk版本必須是r8e版本以上,即使你已經有這些已經準備好,還要注意一點是ndk編譯的時候預設採用ndk toolchain version 4.6的形式去編譯,這個時候就會出現 error thread in namespace std does not ...

cocos2dx 3 0 學習資源

目前看見的cocos2dx 3.0 學習資源 官方的英文 我也在wiki上看了一會,有的還用有道詞典查詢的單詞什麼的。史上最坑爹的遊戲 holdtail 目前資料很少,mac下開發的資源就更少了。如果有朋友看見其他資源可以告訴我啊,謝謝 cocos2dx 3.0基礎知識 cocos2dx 3.0 a...

cocos2d x 3 0建立專案

之前一直用的是cocos2d x 2.3版本,使用tools裡面的create project.py指令碼可以很方便的建立專案。今天更新為3.0後,發現新版建立專案的方式有了很大的改變,於是在這裡記錄一下。在3.0的根目錄下有乙個setup.py的指令碼,用命令列定位到該指令碼所在目錄並執行它 或者...