那些年,我做小游戲碰到的坑

WebGL離屏畫不出來

原因:
當前的GLContext不是預期的孵淘,導致FBO綁定的不對

繪制某一張圖時時黑色的

原因:
WebGL和ES2中NPOT(non-power-of-two)的紋理并不是完全支持蒲障,NPOT的紋理環(huán)繞方式只能用GL_CLAMP_TO_EDGE,紋理過濾只能用GL_NEAREST或GL_LINEAR瘫证,且不能用mipmap揉阎。如果紋理參數(shù)設(shè)置了不支持的類型,shader在采樣時會直接輸出黑色背捌,且無任何報錯毙籽。

進入小游戲屏幕一直閃

原因:JS的不合理調(diào)用,開發(fā)商在適配屏幕比例后會一直設(shè)置寬高并清空FBO毡庆,導致閃屏坑赡。

WebGL畫不出某一張圖像

原因:我們的紋理數(shù)據(jù)默認是預乘Alpha的。WebGL可以設(shè)置紋理存儲方式為unPremultiplyAlpha么抗,這時要把紋理數(shù)據(jù)的alpha通道逆預乘毅否,才能保證shader中輸出的結(jié)果正確。

WebGL渲染偶先字體亂碼

原因:在切換場景時乖坠,WebGL紋理對象被釋放搀突,但JS GC時刪除紋理的操作命令發(fā)生在了離屏Canvas2D上下文,導致刪除了有用的紋理(舉例該紋理句柄為7號)熊泵,之后離屏Canvas2D在創(chuàng)建新的紋理時仰迁,OpenGL會從復用池里返回句柄7號,這導致JS在操作7號紋理時顽分,其實GPU上的紋理并不是開發(fā)商預期的徐许。

WebGL渲染黑屏

原因:WebGL綁定FBO或者RBO時,會傳一個Undefined來回到默認的RBO卒蘸。這時本地解析JSObject時會解成0雌隅,這在OpenGL中相當于解綁了FBO翻默。所以當JS調(diào)用bindFramebuffer/bindRenderbuffer時,JS傳Undefined恰起、null Native會綁定FBO\RBO為默認對象修械。

渲染圖像花屏

原因:在JS中,開發(fā)商在Canvas2D的環(huán)境創(chuàng)建了JSImage,但在WebGL環(huán)境也使用了检盼,由于在Native兩種環(huán)境不屬于同一個GLContext肯污,改成共享紋理解決。

復用紋理黑屏

原因:復用紋理使用glCopyTexSubImage2D, 復制的目標紋理要有內(nèi)存吨枉,不能只有句柄蹦渣。
OpenGL的局部更新操作,都要求目標對象已經(jīng)有內(nèi)存空間貌亭。

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0);

glActiveTexture(GL_TEXTURE0);
targetTexture->resetTextureStorage();
targetTexture->bindToTarget(bindTarget);
glTexImage2D(bindTarget, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

glCopyTexSubImage2D(target, level, 0, 0, 0, 0, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, oldFbo);
glBindTexture(GL_TEXTURE_2D, targetTexture->textureId());

Draw call Crash

原因:頂點數(shù)據(jù)或索引數(shù)據(jù)傳的有問題, 上下文被污染柬唯,其他上下文的操作修改頂點數(shù)據(jù),導致頂點數(shù)據(jù)非預期圃庭。

畫出的紋理不對锄奢,不是目標紋理,而是上一幀用到的紋理

原因:用戶創(chuàng)建了多個sharedCanvas冤议,但SharedCanvas只支持單例斟薇,所以只有第一個有對應的GPU紋理,由于我們的紋理是懶加載恕酸,當數(shù)據(jù)源沒有數(shù)據(jù)時堪滨,沒有繼續(xù)調(diào)用TexImage2d,bindTexture, 導致這一幀的綁定紋理是上一幀的。改為解綁解決蕊温。

JS引擎設(shè)置低于60的幀率時袱箱,渲染是閃屏

原因:Egret引擎的做法是在60幀的RenderTicker之上,自己封裝一個調(diào)用Ticker, skip幀來達到控制幀率的效果义矛。由于WebGL默認是preserveDrawingBubffer=false, 所以有DrawCall的話发笔,在Skip的時間里,native是一直保持空rbo的狀態(tài)凉翻。

Draw Call Crash & 模型扭曲

原因:JS傳過來的多個TypedArray是基于同一個ArrayBuffer做不同偏移得到的了讨,而Native在解TypedArray指針時沒有加上這個偏移量,導致從加載到OpenGL Buffer內(nèi)容不符合預期制轰,模型頂點的位置前计、紋理坐標全是錯誤數(shù)據(jù),多次調(diào)用Draw Call后垃杖,由于頂點數(shù)據(jù)不符合預期男杈,導致GPU driver IOAF error code4 (GPU Hang Error).

轉(zhuǎn)場動畫黑屏、花屏

原因:在JS層傳錯了FBO ID调俘,導致上屏的FBO COLOR_ATTACHMENT的RBO被改成錯誤的伶棒。

轉(zhuǎn)場動畫后渲染黑屏

原因:在轉(zhuǎn)場后開發(fā)商使用WebGL解綁WebGL RBO旺垒,由于native會判斷如果是-1的話綁定默認的RBO。
但從JSC取值是是取double類型肤无,OpenGL傳參時是GLuint先蒋,double的-1轉(zhuǎn)無符號是0,導致錯誤舅锄。

渲染偶現(xiàn)的黑屏鞭达、花屏,報錯Execution of the command buffer was aborted due to an error during execution.

原因:開發(fā)商記住了編譯后的的uniform皇忿、vertexAttrib的slot, 并在之后使用。
在iOS的PVR架構(gòu)GPU下坦仍,一些沒有用到的shader變量會被優(yōu)化掉鳍烁,開發(fā)商會一直試圖對一個不存在的Uniform、vertexAttrib傳值繁扎,而在Native解他們的slot時幔荒,會導致解除的ID不代表真正想要的那個Uniform、vertexAttrib梳玫。
開發(fā)商一直對shader變量傳錯誤的值爹梁,導致Execution of the command buffer was aborted due to an error during execution.錯誤。
解決方案:
每次寫shader變量時確認是否可用提澎。

內(nèi)存問題

原因:開發(fā)商會出現(xiàn)不主動調(diào)delete刪除OpenGL對象姚垃,導致大量OpenGL對象堆積在GPU,這部分的內(nèi)存占用是算在VM里的盼忌,其實CPU的占用并不多积糯。
解決方案:
在GC時主動刪除OpenGL對象解決。

渲染偶現(xiàn)的Crash

原因:為了優(yōu)化內(nèi)存管理谦纱,當JS GC時我們會刪除對應的OpenGL對象看成,GC回收不可控.
當deleteBuffer后,Buffer在GC之前跨嘉,buffer的ID由OpenGL復用返回給了其他createBuffer川慌,會導致GC時刪除的是有用的Buffer, 導致頂點數(shù)據(jù)錯誤,最終導致Crash.
解決方案:
deleteBuffer后清除本地的管理類解決祠乃。

渲染偶現(xiàn)的花屏

原因:為了優(yōu)化內(nèi)存管理梦重,當JS GC時我們會刪除對應的OpenGL對象,GC回收時機不可控.
但開發(fā)商預期在createTexture返回的對象跳纳, 在BindTexture后忍饰,即使在GC后已綁定的texture依然可用,這是WebGL的一個特征寺庄。
解決方案:
優(yōu)化了內(nèi)存管理釋放規(guī)則解決艾蓝。

小游戲顯存中存在重復的紋理

原因:開發(fā)商的一些不規(guī)范行為會導致顯存中存在重復的紋理力崇,如第三方引擎會自動將小游戲所用的圖像資源合成一個大的紋理圖集,這樣方便管理和提高渲染效率赢织,但開發(fā)商在JS層持有住了所有圖像亮靴,導致GPU里存在大量的冗余紋理。
解決方案:
1.實現(xiàn)紋理的LRU緩存于置,淘汰的紋理保存到沙盒里茧吊,使用時再恢復到GPU。
2.加載紋理盡量復用八毯,如texImage2D的最后一個參數(shù)是image或Canvas搓侄,會直接復用紋理。

小游戲死鎖卡住

原因:JS core 的JSContext會在創(chuàng)建它的線程創(chuàng)建JS虛擬機话速,虛擬機會在這個現(xiàn)場添加自己的JS runloop讶踪。在需要在其他線程移步執(zhí)行此JSContext中的JS代碼時,會有一定概率死鎖泊交。
解決方案:
JSContext的創(chuàng)建乳讥、執(zhí)行代碼全部都放在一個線程完成。

渲染過程Crash廓俭,掛在紋理GL命令

原因:我們的開放數(shù)據(jù)域和主域是分別獨立的線程云石,但JS的sharedCanvas在兩個域都可以訪問,導致它在底層的不同OpenGL context之間產(chǎn)生競爭研乒,導致偶先的Crash汹忠。
解決方案:
在上層做邏輯保護,加GPU鎖告嘲,避免同一份GPU資源在不同OpenGL context中產(chǎn)生競爭問題错维。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市橄唬,隨后出現(xiàn)的幾起案子赋焕,更是在濱河造成了極大的恐慌,老刑警劉巖仰楚,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隆判,死亡現(xiàn)場離奇詭異,居然都是意外死亡僧界,警方通過查閱死者的電腦和手機侨嘀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捂襟,“玉大人咬腕,你說我怎么就攤上這事≡岷桑” “怎么了涨共?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵纽帖,是天一觀的道長。 經(jīng)常有香客問我举反,道長懊直,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任火鼻,我火速辦了婚禮室囊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘魁索。我一直安慰自己融撞,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布蛾默。 她就那樣靜靜地躺著懦铺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪支鸡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天趁窃,我揣著相機與錄音牧挣,去河邊找鬼。 笑死醒陆,一個胖子當著我的面吹牛瀑构,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播刨摩,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼寺晌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了澡刹?” 一聲冷哼從身側(cè)響起呻征,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罢浇,沒想到半個月后陆赋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡嚷闭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年攒岛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胞锰。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡灾锯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗅榕,到底是詐尸還是另有隱情顺饮,我是刑警寧澤吵聪,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站领突,受9級特大地震影響暖璧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜君旦,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一澎办、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧金砍,春花似錦局蚀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鹅巍,卻和暖如春千扶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背骆捧。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工澎羞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敛苇。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓妆绞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親枫攀。 傳聞我的和親對象是個殘疾皇子括饶,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容