如何处理 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 游戏编程初学者指南》即将推出!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章