Link

首页

Tweet

书单

about me

Command

友情链接

Category

Everyday Stage3D (一)


        很久没有写东西了,因为工作和一些私人的事情,blog一直处于待更新状态。前阵子一直想着做Starling视频教程,为此事还在中文站的群里讨论过几次,但一直没有付诸实施,视频教程的内容已经基本准备完成,只是一直没有录制,希望近期能够完成吧,也许年前就能完成,和朋友开玩笑的说2012过了末日之后就开始弄,算是为劫后余生庆祝一下。

        从今天开始我将主要更新stage3D的内容,争取每天写一点,大家有什么意见或者疑问欢迎微薄艾特我(weibo.com/mebiusashan),对于大家疑问比较多的问题,我也将整理一下,最后看看能不能整理成册,弄个PDF,正确做一份比较完善的stage3D学习手册。这里关于GPU理论的东西会在用的时候简单说明一下,我也并非图形图像方面的专家,我也会尽量找一些官方的资料贴到最后的参考列表中,大家有什么好的资料也可以联系我,微博或者E-mail(mebius@ashan.org)都可以,E-mail的内容我一般都会即时回复,微博可能会慢一些。

        这是第一篇,也是非常简单的一篇,从我学习的经验来看,很多人喜欢从理论入手,不过个人感觉理论内容过于复杂庞大,而且不利于提高学习的兴趣,所以我还是以实践为主,力争让大家在最短的时间内能够上手操作。

        从最简单的开始说起,我们通常要启动GPU的时候需要一个先决条件,就是在应用程序的标签中开启GPU加速功能,网页和本地的AIR应用(包含移动应用)的开启方法略有不同,网页的方式是在HTML页面中添加一个wmode="direct"标签,而AIR的开启方式为将配置文件的renderMode标签打开,并改为direct,这样就可以正常的开启GPU功能。当然,如果你的硬件确实不在支持范围之内,那么上述操作都是无用功。

        下面开始编写一个能够开得见的程序。这个程序非常的简单,我们只是在界面上显示一个黑色的背景,这个背景中没有任何内容,在下一篇中我们再编写一个像样的看得见的图像DEMO。

        首先我们要知道,stage3D层一共有多少个,在普通的PC设备中,我们共有4个stage3D层可用。但是在一般项目制作中我们只是用其中一个,也就是第一个。所以,我们在一个程序的开始,首先要判断当期的设备有几个可用的图层,如果可用图层为0,那么就意味着你后面的所有代码将没有任何用处,因为当期的设备并不支持GPU加速。我们通过下面的语句来获取stage3D层的数量。

stage.stage3Ds.length

当你确认你的设备确实可用的时候你可以初始化你的stage3D图层,我们说了,我们需要使用的一般为第一个图层。那么我们对这个图层进行事件侦听,来获取他时候可以启用或者启用的过程中是否发生错误。

if( stage.stage3Ds.length > 0 )
{
this._stage3d = stage.stage3Ds[0];
this._stage3d.addEventListener(Event.CONTEXT3D_CREATE,created_handler);
this._stage3d.addEventListener(ErrorEvent.ERROR, created_error_handler );
this._stage3d.requestContext3D( Context3DRenderMode.AUTO );
}

请注意最后一句,Context3DRenderMode的类型一共有两种,AUTO是自动,系统会更需当前环境自行选择运行方式GPU还是软件加速,另外一种是SOFTWARE,直接以软件渲染方式运行。

       如果当前你的设备确实不能使用GPU,好的,那么你可以做一个提示,比如trace("GPU启动失败或设备丢失!");

或者一些其他的处理手段。

       如果你成功的启用了GPU,那么好,请看下面的代码:

private function created_handler (evt:Event):void
{
trace( "GPU设备类型:",this._stage3d.context3D.driverInfo );
this._context3d = this._stage3d.context3D;
this._context3d.configureBackBuffer( 300,300,0,true);
}

大家注意,很多人以为stage3D就是GPU渲染的关键或者全部,其实这是错误的,因为stage3D仅仅代表一个图层,而图层内容的context3D才是可以和GPU通信的管道,context3D才是关键。换句话说,你所有的GPU数据,全部需要通过context3D这个管道来传输。更加直白的理解方式你会在下一篇中看到,几乎所有的代码都需要调用context3D,目前你也可以理解为大部分的draw操作都是context3D提供的API。

        OK!我们将上面的function稍稍修改一下,添加一个MouseEvent事件来模拟一下设备丢失。

private function created_handler (evt:Event):void
{
trace( "GPU设备类型:",this._stage3d.context3D.driverInfo );
this._context3d = this._stage3d.context3D;
this._context3d.configureBackBuffer( 300,300,0,true);
stage.addEventListener(MouseEvent.CLICK, click_handler );
}
private function click_handler(evt:MouseEvent):void
{
this._context3d.dispose();
}

这是修改后的代码片段,我们看到,当我们执行click的时候,我们将context3D对象所连接的所有资源全部释放,这一操作模拟了设备丢失的情况。测试你的程序,你会发现,当我们点击了舞台之后,会立刻打印出GPU设备类型: OpenGL (Direct blitting) (笔者的话:我是Mac OS X系统,所以会提示OpenGL,windows操作系统与此不同)。这说明,如果你在程序运行的时候,丢失了设备,同时没有删除stage3D的Event.CONTEXT3D_CREATE事件侦听,那么系统还会自动监听创建事件,并且为你生成一个新的context3D对象。这个小小的demo说明一个问题,如果你需要GPU操作复原这部分功能,请不要尝试自己去刷新或者使用Timer来判断当前GPU使用可以启动,因为player部分已经替你做了相关操作。如果你自己实现了相同的功能,那么可能会在某一个时刻,重新创建context3D对象。

        OK!这部分先到这里,后面的内容会更加精彩,大家如果喜欢,请微博留言给我。