一直以來很多Stage3D開發者都在為3D模型在2DUI上顯示的問題頭疼。Stage3D一直是在 Stage2D下面。為了做到3D模型在2DUI上顯示通常大家有幾種實現方式,下面來說說這幾種實現方式吧。
實現方式1:
在2DUI上挖個洞透過去顯示3D層。這種做法的缺陷在於如果兩個UI界面同時打開就會UI錯層顯示錯亂。為了解決這問題很多程序員選擇了當挖洞顯示3D的UI打時把其他界面隱藏掉,用戶體驗超差。
實現方式2:
利用Context3D 的 drawToBitmapData API 實時將3D層渲染的物價繪制到BitmapData上。然后再添加到2DUI上。這種做法的缺陷在於每次drawToBitmapData函數。每次從顯卡draw圖然后再回傳回來的開銷非常大,會導致幀頻下降。而每次draw圖會產生大量的內存。有人可能會說我draw圖的時候 按時間間隔去draw,減少一部分開銷。其實都一樣畫面不流暢。
實現方式3:
把3D模型渲染成序列幀位圖。再實現一個位圖播放器在2DUI上顯示。這樣做法會導致所需要加載的位圖量非常大,內存大小就可想而知了。
好吧以上都是我們的常用做法。實在惡心,很多程序員會選擇使用第3方提供的 3DUI 例如 starling等來實現。沒錯這是最終的解決方案,但是頭疼的問題又來了坐標轉換是個麻煩的問題。再一個就是 starling 對於AS3程序員來說用起來總不是那么得心應手。怎么辦....怎么辦....痛苦糾結針扎中。
朋友如果你還在為以上這些問題頭疼、糾結、針扎中那么下面我向你推薦下另一種幾乎可以解決以上你所擔心的任何問題。老規矩先上圖吧。
怎么樣呢?是否感覺很贊呢?
話說有一天在開晨會的時候同事和我說他想到一個方式可以解決UI互斥的問題。抱着半信半疑的心里我看了下他的實現方式。下面我就來說說吧
其實原理還是前面說到過的 實現方式1 只是在這個做法上做了些優化。大家都知道as3中的 Graphics 畫一個矩形在同一個地方畫兩次就會挖個洞出來。首先檢查到帶有3D模型的UI 面板是否和其他UI重疊。如果重疊則把最上層的UI保留,下層的UI畫空。這樣就可以解決了。但是問題又來了一個帶3D模型的UI 和一個普通2DUI 顯示沒問題了。那么兩個帶3D模型的UI 疊在一起就可以看到另一個UI上的模型跑到這個UI上來了。 原因是模型都是渲染在同一個Context3D上一旦畫空了就全顯示出來了。為了解決這個問題我們得改下3D引擎的渲染方式了。首先把要再UI上顯示的3D元素都做一個標間,以便與在引擎底層用來區分渲染。
當檢查到標記的時候先調用下 Context3D清理一次深度
context.clear(0, 0, 0, 1, 1, 0, Context3DClearMask.DEPTH);
好了 下面我們來整理下我們渲染在2D界面上的3D物件的渲染順序:
燈光--> 網格(作為背景底板)---> 3D模型
好了順序清楚了流程,現在開始渲染。
燈光就無視了。只要你調好坐標能照到你的模型即可,無需做特殊處理。重點來了,在渲染背景底板的時候,我們再調用一次context.clear(0, 0, 0, 1, 1, 0, Context3DClearMask.DEPTH);再渲染。
清理深度這個主要是用來控制不讓下層的3D物件因深度問題而透到前面來。好了底板已經渲染OK了現在再來重復一次渲染底板的方式再渲染一次模型吧。好了現在看上去還好一切正常現在多創建幾個疊加試試
OK 大功告成一切正常。最后還是聲明下如果有條件的朋友還是建議自己寫3DUI 來做。不會寫的也沒關系可以考慮用 starling 或第3方的一些類庫來實現。