如何處理 Stage3D 渲染內容的丟失

Stage3D渲染內容會丟失,並使已建立的3D場景瞬間遭受滅頂之災。這個問題幾乎無法避免,並且尚未完美解決。那渲染內容丟失是怎樣產生的?爲什麼造成如此大的影響?怎樣解決這個問題可讓應用程序正常運行呢?
今天的文章將就此探討,如何處理Stage3D渲染內容丟失可使3D場景保存完好。

在開始基於Stage3D的應用創建時,要獲得用於3D場景渲染的Context3D對象需發起申請請求(注:通過調用 Stage3D 對象的 requestContext3D() 方法)。渲染內容丟失的問題本身就說明是因爲丟失了Context3D對象。
出現此問題的原因很多,通常還不是因爲Stage3D應用。比如在win7系統中,當按下Ctrl+Alt+Delete鍵時會出現類似鎖定計算機啓動任務管理器的菜單選項,這就會引起渲染內容丟失。但這不是唯一的可能,還有些情況,在某些屏保程序激活時又或筆記本蓋子合上時也會引起渲染內容丟失。甚至可以通過調用Context3D.dispose()方法來模擬渲染內容丟失事件。
所以,最傾向的一種假設是——對於大部分Flash應用,在任何情況下任何原因都可能引起渲染內容丟失(囧)解決辦法只能是儘可能地妥善處理。

當丟失Context3D對象時會對正在處理的應用造成什麼影響呢?當然,肯定無法繼續渲染已有的Context3D實例,也就意味着將無法對3D場景進行渲染。在等待獲得新渲染內容的這段時間裏,屏幕會顯示正在加載中之類的信息

更復雜的問題或許是你剛纔用Context3D類所創建的紋理、頂點緩衝及着色器程序已不可用,也就意味着要想恢復之前的3D場景,這些都需要重新創建。怎樣做的選擇在你,一般會涉及到通過諸如Texture.uploadFromBitmapData的功能將上傳至GPU(圖形處理單元)的數據進行備份。不幸的是,這意味着需要佔用更多的系統內存才能恢復這些數據。
你或許考慮其它可替代的辦法來重建這些資源,比如重新下載後再重新上傳資源,又或簡單地認爲渲染內容丟失是一個“fatal error(致命的錯誤) 重新開始該應用程序、遊戲級別或重啓即可。

但如何知道Context3D對象丟失了呢?如果查閱AS3文檔,你會注意到文檔中並沒有關於此類情況的事件偵聽。

而在程序運行時,FlashPlayer會調用Stage3D的另一個事件偵聽:Event.CONTEXT3D_CREATE事件

因此你需要在事件處理器中編寫類似如下的代碼作爲補充:


  1. var stage3D:Stage3D;
  2. var context:Context3D;

  3. // Request a context as part of starting up the Stage3D-based app
  4. stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreated);
  5. stage3D.requestContext3D();

  6. function onContextCreated(ev:Event): void
  7. {
  8.         // Save the old context so we can tell if this was the first context or a replacement
  9.         // one due to context loss
  10.         var oldContext:Context3D = context;
  11.         context = stage3D.context3D;

  12.         // create all textures, vertex buffers, index buffers, and shader programs and upload them... 
  13.         if (oldContext)
  14.         {
  15.                 // had a context before
  16.                 // this means we lost it and got a new one
  17.         }
  18.         else
  19.         {
  20.                 // getting a context is a normal part of app startup
  21.                 // we have one for the first time (i.e. during app startup)
  22.                 // so continue starting up the app...
  23.         }
  24. }
複製代碼

你將會找到適合自己應用程序的解決辦法,上面的是一種通用的策略:即在當渲染對象被創建時,(重新)建立並(重新)上傳之前所用的3D資源。另一種策略是將3D資源從應用程序中剝離,當需要創建時就可以很容易的進行替換。相關代碼(注:原文pseudo-code譯作僞代碼)如下:
  1. class MyTexture
  2. {
  3.         var bmd:BitmapData;
  4.         var texture:Texture;
  5. }
  6. class MyScene
  7. {
  8.         var textures:Vector.<MyTexture>;

  9.         function onContextCreated(ev:Event): void
  10.         {
  11.                 // Re-create and re-upload all textures
  12.                 for each (var tex:MyTexture in textures)
  13.                 {
  14.                         tex.texture = context.createTexture(
  15.                                 tex.bmd.width,
  16.                                 tex.bmd.height,
  17.                                 Context3DTextureFormat.BGRA
  18.                         );
  19.                         tex.texture.uploadFromBitmapData(tex.bmd);
  20.                 }
  21.         }
  22. }
  23. class MyApp
  24. {
  25.         // Users don't use Texture objects directly
  26.         // Instead they use the middle-man: MyTexture
  27.         var tex:MyTexture;

  28.         function render(): void
  29.         {
  30.                 context.setTextureAt(0, tex.texture);
  31.         }
  32. }
複製代碼

術語及理解參考:
1.       
Flash Molehill 簡單例子
          http://www.pixelbender.cn/?p=381
2.       [Stage3D]GPU渲染的噴泉粒子
          http://www.cnblogs.com/flash3d/archive/2012/02/01/2332393.html
3.       StarlingAPI 參考 處理丟失的渲染內容
          http://www.starlinglib.com/asdoc/1.2/starling/core/Starling.html
4.       發行說明 | Flash Player® 11.4、AIR® 3.4 處理設備丟失

          http://helpx.adobe.com/cn/flash-player/release-note/fp_114_air_34_release_notes.html


另:本文
contextStarling中文站譯作渲染內容
特別推薦:
A閃的Everyday Stage3D系列 
特別廣播:白藍紫翻譯的中文版《
Stage3D 遊戲編程初學者指南》即將推出!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章