(转)Away3D4.0和Starling协作教程
2014-07-29 19:44:00前言
在新发布的Away 3D 4.0 Gold版本中,包含了一个叫做Stage3DManager的实现Stage3D结合其他ActionScript库的渲染的API。在这个教程中,我们将通过结合Away3D和Starling架构创建一个高效的渲染循环(rendering loop),自从Stage3D加入到Air和Flash Player中,出现了很多新框架,他们通过不断的升级,尝试发挥stage3D的最大性能。其中Away3D在GPU优化方面表现良好,令开发者可以创造出令人难以置信的3D交互体验,类似的,Starling是一个旨在更完全发挥Stage3D性能的2D GPU加速框架。结合这两个东西的前提条件是一些APIs方面的改动,否则这两个框架就会在各自的Stage3D实例中渲染。可惜的是此前没有引擎可以做到这些。令人庆幸的是,随着新的Away3D 4.0 Gold版本发布,提供了融合多框架到一个Stage3D实例中的功能,我们可以轻松的结合无论多少个Away3D和Starling实例。但事实上,并不是所有基于Stage3D的框架都可以被使用——详情请见页面底部。在这个教程中,底层和顶层是Starling层,中间层是Away3D层。
原理介绍
在普通项目中,如果仅仅使用了Away3D,Stage3D内容将在实例内部处理。这虽然操作简单,但是这造成了不同实例间协作的困难。我们需要的是通过一个Stage3D实例来管理所有的Stage 3D框架的实例。这可以通过Stage3DManager
和Stage3Dproxy
类来实现。
// Stage manager and proxy instances
// Stage 管理和代理实例
private var stage3DManager : Stage3DManager;
private var stage3DProxy : Stage3DProxy
/**
* Global initialise function
*全局初始化函数
*/
private function init():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
initProxies();
}
/**
* Initialise the Stage3D proxies
*Stage3D代理初始化
*/
private function initProxies():void
{
// Define a new Stage3DManager for the Stage3D objects
// 为Stage3D对象定义一个新的Stage3DManager ;
stage3DManager = Stage3DManager.getInstance(stage);
// Create a new Stage3D proxy to contain the separate views
//创建一个新的Stage 3D 代理来管理不同的视图。
stage3DProxy = stage3DManager.getFreeStage3DProxy();
stage3DProxy.addEventListener(Stage3DEvent.CONTEXT3D_CREATED, onContextCreated);
stage3DProxy.antiAlias = 8;
stage3DProxy.color = 0x0;
}
我们可以通过getInstance()
方法调用通过单例模式使用的Stage3DManager类,通过这个实例,我们可以调用下一个可用的Stage实例渲染。但是这不是马上执行的,我们必须侦听Stage3DEvent.CONTEXT3D_CREATED
时间,等待Stage分配实例。当我们处理Stage3DProxy时,就可以设置一些参数包括全局抗锯齿,背景颜色。
建立图层
一旦我们侦听到了Stage3DEvent.CONTEXT3D_CREATED
事件,我们就可以创建一些渲染用的图层。正如前面所说,我们将有一个Away3D场景以及两个Starling场景,我将详细叙述建立这些渲染图层的条件,而不是每个图层的内容。
private function onContextCreated( event:Stage3DEvent ):void
{
initAway3D();
initStarling();
initMaterials();
initObjects();
initButton();
initListeners();
initListeners();
}
/**
* Initialise the Away3D views 初始化Away3D view。
*/
private function initAway3D():void
{
// Create the first Away3D view which holds the cube objects.
// 创建第一个包含立方体的Away3D view
away3dView = new View3D();
away3dView.stage3DProxy = stage3DProxy;
away3dView.shareContext = true;
hoverController = new HoverController( away3dView.camera, null, 45, 30, 1200, 5, 89.999 );
addChild( away3dView );
addChild( new AwayStats( away3dView ));
}
/**
* Initialise the Starling sprites
* 初始化 Starling sprites
*/
private function initStarling():void
{
// Create the Starling scene to add the background wall/fireplace.
// This is positioned on top of the floor scene starting at the top of the screen.
// It slightly covers the wooden floor layer to avoid any gaps appearing.
//创建Starling 场景并且添加背景,这将会被安置在地板场景之上,但会轻微的覆盖地板层,避免缺口出现
}
其中onContextCreated
方法是典型的方式定义了3D场景,对象,材质,事件侦听器,以及实现Starling实例化。在initAway
3D方法中,我们和往常一样为Away3D场景建立了View3D对象,另外我们还通过设置了.stage3DProxy
属性共享到了Stage3DProxy实例,并且设置.shareContext=true
允许共享执行。相似的,在initStarling 方法中创建了Starling场景。每个场景都需要传递一个引用到Starling sprite场景,舞台和分享的Stage3D,同样我们会传递一个定义了视口大小的长方形和一个引用到我们的Stage3D实例。最后,他们都可以通过Stage3DProxy实例的.viewPort
和 .stage3D
属性控制。
如果想重新设置Starling Sprite的视口大小,请在Starling外部修改长方体的尺寸,这样
Starling.viewPort
会返回一个科隆的长方形,而不是原来那个的引用。将它传递给构造器,并且修改外部的长方体,Starling就可以正确的渲染。现在Stage3D的共享实例拥有Away3D场景和Starling Spite层的引用,其他的图层用同样方式创建,正如你在下面的实例中可以看到的一样,你可以通过鼠标转动,拖拽它。 渲染的时候,首先呢,最下一层,也就是最开始渲染的一层,是可以旋转的棋盘格样式的一个Starling图层,在这之上是一个含有5个交叉放置的立方体的Away3D场景,它在一个网格之上。最上面,也是最后渲染的,是一个Starling粒子效果图层。
渲染
当Stage3D被共享时,我们在渲染过程中需要禁用几个函数。从最简单的角度来说,渲染一个场景需要三步,1:场景被清空-clear()
方法,2:渲染元素,-drawTriangles()
;3:显示在屏幕上:present()
;其中第一步和第三部导致了Stage3D不能被共享。现在呢,away3D和Starling已经被结合到了一个Stage3D的实例中,接下来要考虑的就是在Stage 3DProxy中考虑清理*.clear()
和显示.present()
了。Stage3DProxy类提供两种渲染设置,两者很相似但是提供对清除clearing和展示presenting*不同的控制。手动控制呢我们需要精确调用Both are described here.Stage3DProxy.clear() 和 .present()方法来渲染,然而自动控制可以轻松地为我们做到这一切。
控制渲染-手动
/**
* Set up the rendering processing event listeners
* 建立渲染进程侦听器
*/
private function initListeners():void {
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
/**
* The main rendering loop
* 主渲染循环
*/
private function onEnterFrame(event:Event):void
{
// Clear the Context3D object
// 清空Context3D 对象
stage3DProxy.clear();
// Render the Starling animation layer
// 渲染Starling动画图层
starlingCheckerboard.nextFrame();
// Render the Away3D layer
// 渲染Away3D图层
away3dView.render();
// Render the Starling stars layer
// 渲染Starling 星星图层
starlingStars.nextFrame();
// Present the Context3D object to Stage3D
// 在Stage3D中呈现Context3D
stage3DProxy.present();
}
在上面一段代码中,我们侦听了舞台实例的ENTER_FRAME
事件,接着在侦听函数中,我们调用了stage3DProxy.clear()
方法,然后依次渲染了各个图层,最后调用了stage3DProxy.present()
方法,这是我们可以完全地控制图层的渲染顺序和调用清除.clear
和呈现.present()
方法。
更加轻松的方法-自动控制
/**
* Set up the rendering processing event listeners
* 建立渲染侦听器
*/
private function initListeners():void
{
stage3DProxy.addEventListener( Event.ENTER_FRAME, onEnterFrame );
}
/**
* The main rendering loop
* 主渲染循环
*/
private function onEnterFrame( event:Event ):void
{
// Render the Starling animation layer
// 渲染Starling动画图层
starlingCheckerboard.nextFrame();
// Render the Away3D layer
// 渲染Away3D图层
away3dView.render();
// Render the Starling stars layer
// 渲染Starling星星图层
starlingStars.nextFrame();
}
这种方法的巧妙之处在于,它的ENTER_FRAME
侦听器是加在Stage3DProxy object
而不是在舞台中,它自己在内部调用了clear()
和present()
方法,然后由你决定如何渲染。上面的例子中你可以看到在事件侦听方法中被渲染。可以在这里下载演示文件。