cocos2dx 如何做到無卡頓載入紋理?
有這麼一個需求, 不允許有loading界面, 然後要動態載入一些紋理進來, 界面不許卡頓 就像跑酷那類遊戲那樣, 但是需要載入的紋理比那些大就是了。 嘗試過 多線程載入, 可是opengl非線程安全, 導致 部分跟opengl交互的還是要放在主線程, 最終還是會卡頓下下 請問, 這類需求, 大神們都是怎麼解決的
------------------------------------ 看了下回答,感覺有一部分沒明白我的意思,以我了解到的知識,子線程好像只能做做解壓紋理的事,最後上傳紋理還是要調用ooengl的函數,可是cocos2dx現在所使用的版本好像不支持多線程,所以這部分交互只能放在主線程,上傳個大的就會掉幾幀,如2048*2048尺寸的,給人感覺就是卡了下
cocos2dx 我不是很熟,以下回答源於我在 NVIDIA 的工作心得。先解釋下 glTexImage2d,它會將數據從 CPU 內存通過 PCIE 上傳到 GPU 內存。不使用 PBO 時它是一個阻塞 CPU 的函數,數據量大時肯定會卡。
解決方法是在子線程也創建一個 context,同時 share 資源給渲染的主線程。
必須要 share 喲。
https://www.khronos.org/registry/egl/sdk/docs/man/html/eglCreateContext.xhtml
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, EGLint const * attrib_list);
share_context
Specifies another EGL rendering context with which to share data, as defined by the client API corresponding to the contexts. Data is also shared with all other contexts with which share_context shares data. EGL_NO_CONTEXT indicates that no sharing is to take place.
那麼,在子線程調用 glTexImage2d 時就不會卡到主線程的渲染。
另外,科普下 opengl 的線程不安全,它存了很多東西在線程的局部空間中,即 thread-local storage (TLS)。在沒有綁定過 context (eglMakeCurrent / wglMakeCurrent)的線程中調用 opengl 函數是沒有意義的,因為這個線程中嘛都沒有。它們會抱怨:
啥是 opengl,能吃嘛?
而一個 context 在同一時間只能被一個線程綁定。
CCTextureCache::addImageAsync(...) 可以解決你的問題。如果還覺得不爽,可以照抄一個自己改進改進。目前cocos2d-x裡面有三個非同步的點,一個在CCTextureCache::addImageAsync裡面,一個在network/HttpClient裡面,還有一個在editor-support/cocostudio/CCDataReaderHelper.cpp裡面
最傻X的方法是在切換場景的過程中做個中間場景專門載入。
我用的就是這個方法。
也許你還是可以放在兩個線程里。當主線程沒有在使用OpenGL的時候,資源線程才去載入資源。
2種方法:1,2個線程1個OpenGL context,2個線程一個做渲染,一個做邏輯
2,2個線程2個context,主渲染線程維護狀態,提交dc;輔助渲染線程做vb,texture的數據copy,shader的編譯等。GPU會在兩個context之間同步,有隱性開銷
其實單線程下規劃好資源依賴應該可以做到不卡的正如樓主所說,最後的紋理生成必須要在GL線程完成,即cocos主線程,所以如果圖片太大是一定會有卡頓的,尤其是跑酷這種對幀數非常敏感的遊戲。我現在的項目也有類似的功能需求,我是做了非同步處理的,圖片大了還是會卡的。樓主要麼降低圖片尺寸試試,要麼就做預載入。iphone5之後的設備至少可以有400多兆內存可以使用,一般情況預載入不會出現OOM。
不需要多線程。卡是因為圖片太大一次載入時間太長,把圖片分割,在遊戲過程中載入進來後,再拼接顯示。
你先載入一部分進入遊戲,然後在遊戲開始後,在遊戲中繼續載入啊,反正玩家也看不出來你在載入資源
我之前做的遊戲是改過cocos2dx的載入pvr圖片的邏輯,允許線程載入pvr圖片,設置圖片載入完的回調更新界面
推薦閱讀: